[JS] 클로저
클로저
클로저란 함수와 함수의 변수가 해석되는 스코프의 어떻게 변수의 유효범위를 지정하는지 이해해야한다.
Javascript는 lexical scoping을 사용한다. 이는 함수를 호출하는 시점에서의 변수 유효범위가 아니라, 함수가 정의된 시점의 변수 유효범위를 사용하여 함수가 실행된다는 것이다.
이러한 lexical scoping을 구현하기 위해, Javascript 함수 객체는 내부 상태에 함수 자체의 코드뿐만 아니라 현재 scope chain에 대한 참조도 포함하고 있다. 함수 객체와 함수의 변수가 해석되는 유효범위(변수 바인딩의 집합)를 클로저라고 한다.
기술적으로 모든 Javascript는 클로저인데, 함수는 객체이고 함수 자신과 관련된 scope chain을 가지고 있기 때문이다. 함수 대부분은 함수가 정의되었을 때의 scope chain을 사용하여 호출되고, 클로저가 개입되었는지의 여부는 중요하지 않다.
function outerFunc() {
var x = 10;
var innerFunc = function () { console.log(x); };
return innerFunc;
}
/**
* 함수 outerFunc를 호출하면 내부 함수 innerFunc가 반환된다.
* 그리고 함수 outerFunc의 실행 컨텍스트는 소멸한다.
*/
var inner = outerFunc();
inner(); // 10
위와 같이 outerFunc의 실행이 종료 되었어도 outerFunc의 내부함수인 x가 아직도 살아있다. 이렇게 이 처럼 자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부함수 밖에서 내부함수가 호출되더라도 외부함수의 지역변수에 접근할 수 있는 데 이러한 함수를 클로저라고 한다.
내부함수가 선언됐을 때의 스코프를 렉시컬 환경이라고 한다. 클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경을 기억해서 자신이 선언된 스코프 바깥에서 호출되어도 그 스코프에 접근할 수 있는 함수를 말한다.
이를 실행컨텍스트 관점에서 설명하면, 내부함수가 아직 유효한 상태에서 외부함수가 종료되어 외부함수의 실행컨텍스트가 반환되어도, 외부함수 실행 컨텍스트 내의 활성객체는 아직 유효한 상태인 내부함수로 부터 계속 참조되고 있으므로 마찬가지로 유효하기 때문에 내부함수에 의해 스코프체인을 통해 계속 참조될 수 있는 것이다.