Closure

어휘적 환경(Lexical Environment)

어떻게 동작하는지

// 코드가 실행되면 스크립트 내에서 선언한 변수들이 Lexical 환경에 올라간다.
// Lexical 환경 - one: 초기화 x / addOne: function

let one; // Lexical 환경 - one: undefined(사용해도 에러는 안남) / addOne: function
one = 1; // Lexical 환경 - one: 1 / addOne: function

addOne(9); // 전역 Lexical 환경 - one: 1 / addOne: function // 새로운 내부 Lexical 환경 - num: 9

function addOne(num) {
    console.log(one + num);
}

addOne(5); // 전역 Lexical 환경 - one: 1 / addOne: function // 새로운 내부 Lexical 환경 - num: 5

내부 Lexical 환경은 외부 Lexical 환경에 대한 참조를 받는다.
코드에서 변수를 찾을 때 내부 -> 외부 -> 전역의 순서로 찾는다.

function makeAdder(x) {  // 전역 Lexical 환경 - makeAdder: function / add3: 초기화x
    return function(y) { 
        return x + y;
    }
}

const add3 = makeAdder(3); // 전역 Lexical 환경 - makeAdder: function / add3: function // makeAdder Lexical 환경 - x: 3
console.log(add3(2)); // 전역 Lexical 환경 - makeAdder: function / add3: function // makeAdder Lexical 환경 - x: 3 // 익명함수 Lexical 환경 y : 2

함수의 Lexical 환경(makeAdder Lexical 환경)에는 넘겨받은 매개변수(x: 3)와 지역변수들이 저장된다.
익명함수 -> makeAdder -> 전역 순서로 변수를 찾는다.

  1. function(y)은 자신이 y를 가지고 있고 상위함수인 makeAdder의 x에 접근 가능
  2. add3 함수가 생성된 이후에도 상위함수의 x에 접근 가능
  3. 이러한 것을 Closure 이라고 한다. Closure는 함수와 그 함수의 렉시컬 환경의 조합이고, 함수가 생성될 당시의 외부 변수를 기억하고 생성된 이후에도 계속 접근 가능
const add3 = makeAdder(3);
const add10 = makeAdder(10);
console.log(add10(5)); // 15
console.log(add3(1)); // 4

makeAdder(10)이 호출되지만 makeAdder(3)에는 아무런 영향을 미치지 않는다. 서로 다른 환경을 가지고 있기 때문에


예문

function makeCounter(){
    let num = 0;

    return function(){
        return num++
    };
}

let counter = makeCounter()

console.log(counter()); // 0
console.log(counter()); // 1 
console.log(counter()); // 2 
console.log(counter()); // 3

내부함수에서 외부함수의 변수인 num에 접근한다.
생성된 이후에 계속 기억한다.
결과로 나온 숫자들은 수정할 수 없다.(은닉화)

댓글남기기