JS는 상위 스코프를 함수의 선언되는 위치에 따라 결정한다. 이를 렉시컬 스코핑이라고 하며, 해당 스포크를 렉시컬 환경이라고 한다. 즉, 특정 함수가 선언되었을 때, 해당 함수와 함수가 참조할 수 있는 상위 스포크를 렉시컬 환경이라고 한다. 이러한 특징을 이용한 것이 클로저이다.
function outerFunc() {
var x = 10;
var innerFunc = function () {
console.log(x);
};
innerFunc();
}
outerFunc(); // 10
innerFunc
를 선언했을 때, 해당 함수의 상위 스코프는 outerFunc
와 전역이다. 따라서 innerFunc
가 실행됐을 때 상위 스코프의 변수인 x
를 참조할 수 있다.
function outerFunc() {
var x = 10;
var innerFunc = function () { console.log(x); };
return innerFunc;
}
var inner = outerFunc();
inner(); // 10
위 코드를 보면 outerFunc
함수를 inner
에 할당했다. outerFunc
가 innerFunc
를 반환하고 유효 범위가 끝났기 때문에(실행되고 실행 컨텍스트 스택에서 제거 됐기 때문에) inner
를 실행하면 오류가 날 것 같지만 그렇지 않고 잘 실행이 된다.
이렇게 특정 내부함수가 자신의 상위 스코프 밖에서(상위 스코프가 종료된 이후) 실행되어도, 해당 내부함수가 선언된 시점의 렉시컬 환경에 해당하는 변수와 함수를 사용할 수 있는 것을 클로저라고 한다.
정리하자면 클로저란, 자신이 선언된 시점의 렉시컬 환경에 해당하는 것을 기억하여 밖에서 호출되더라도 해당 렉시컬 환경의 변수, 함수를 사용할 수 있게 만든 함수이다.