클로저는 함수와 그 함수가 선언될 때 만들어지는 어휘적 환경(Lexical Environmnet
)의 조합이다.
클로저를 이해하기 위해서는 자바스크립트가 변수의 유효범위(Lexical Scope
)를 어떻게 지정하는지(Lexical Scoping
) 알아야 한다.
function A_Func(인자A) {
var 지역_변수A = "Hi";
function B_Func() {
alert(지역_변수A);
}
B_Func();
}
A_Func();
위의 코드를 실행하면,
A
) 하나와 중첩 함수(B_Func
) 하나를 생성한다.B_Func()
는 A_Func 의 내부 함수이므로, A_Func
함수 안에서만 실행될 수 있다. 여기서 주의할 점은 B_Fun()
함수는 지역 변수를 가지고 있지 않다는 것이다. 지역 변수를 가지고 있지 않지만, 외부 함수인 A_Func
함수의 지역 변수에 접근할 수 있기 때문에 B_Fun()
함수 역시 지역변수A
에 접근할 수 있다.A_Func
함수 실행 -> 지역 변수, 내부 함수 생성 후 실행 -> 내부 함수에서 외부 함수의 지역 변수에 접근해 alert("Hi")
를 실행한다.이것은 Lexical Scoping
을 보여주는 한 예시이다.
쉽게 말해서, 함수 내부에서 지역 변수가 선언될 때, Lexical Scoping
이 일어난다. 이 Lexical Scoping
은 지역 변수의 사용 가능해지는 위치가 지역 변수의 선언된 위치에 따라 다르다는 것을 의미한다.
즉, 내부 함수는 외부 함수에서 선언된 변수에 접근할 수 있다.
이제 다음 예를 보자.
function A_Func(인자A) {
var 지역_변수A = "Hi";
function B_Func() {
alert(지역_변수A);
}
return B_Func;
}
const 전역_변수 = A_Func();
전역_변수();
위 코드는 이전에 있던 코드와 동일하게 작동한다. 차이점이 있다면, B_Func
함수가 A_Func
함수 안에서 실행되기 전에 리턴되어 전역_변수
에 할당된다는 것이다.
일반적으로, 어떤 함수 내부에 지역 변수가 있으면 그 지역 변수는 함수가 처리되는 동안만 존재해야 한다. 그러므로, B_Func
이 리턴되면 A_Func
은 종료되며 지역_변수A
에 더 이상 접근할 수 없어야 한다.
하지만, 자바스크립트는 다르다.
자바스크립트는 함수를 생성하면 그 함수의 클로저가 형성되기 때문이다. 지금 같은 경우, B_Func
함수를 리턴하고 있는데 B_Func
함수가 클로저를 형성하기 때문이라고 볼 수 있다. 클로저는 함수와 함수가 선언된 Lexical Environment
의 조합이다. 이 렉시컬 환경은 클로저가 형성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다. 그리고 위의 예시에서 이 모든 지역 변수에는 지역_변수A
가 포함된다.
함수 A_Func
과 전역_변수
가 선언된다. 여기서 전역_변수
는 함수 A_Func
의 반환값인 B_Func
을 참조한다.
B_Func
은 선언될 때 Lexical Scoping
이 발생함에 따라, 외부 함수의 지역_변수A
를 가진 Lexical Environment
를 참조하고 있다.
이에 따라, 참조 -> 참조를 통해 전역_변수()
를 실행하면, 지역_변수A
는 사용할 수 있는 상태로 유지되어 alert("Hi")
가 실행된다.
좀 복잡하지만, 겉핥기 식으로라도 개념이 잡혀가는 것 같다... 다룰 만한 내용들이 더 있지만 시간 관계상 나중에 다뤄보자.