
클로저는 자바스크립트의 고유 개념이 아닌, 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서 사용되는 특성이다.
MDN에서 정의한 클로저
“A closure is the combination of a function and the lexical environment within which that function was declared.”
"클로저는 함수와 그 함수가 선언되었을 때의 Lexical environment(렉시컬 환경)과의 조합이다."
다음은 inner함수를 내부함수로 가지고있는 outer함수를 호출하는 코드이다.
function outer() {
let x = 100;
let inner = function () {
console.log(x);
};
inner();
}
outer(); // 100
outer함수 내에서 내부함수인 inner함수가 선언되고 호출되었다.
-> 이 때 내부함수(inner함수)는 자신을 포함하고 있는 외부함수(outer함수)의 변수 "x"에 접근이 가능하다.
-> inner함수가 outer함수 내부에서 선언되었기 때문이다.
유효범위 scope
scope는 함수를 어디에 선언하였는지에 따라 결정 (Lexical Scoping)
위 코드에서 inner함수는 outer함수 내부에서 선언되었기 때문에, inner함수의 상위 scope는 outer함수이다. (outer함수의 상위 scope는 전역 scope이다.)
내부함수는 자신이 속한 lexical scope를 참조할 수 있다. inner함수의 경우 전역 scope / outer함수 / 자신의 scope를 참조할 수 있다.
이번에는 inner함수를 outer함수 내에서 호출하는 것이 아닌, 반환하는 코드이다.
function outer() {
let x = 100;
let inner = function() {
console.log(x);
}
return inner;
}
let innerFunc = outer(); // outer함수 호출 시 inner함수 반환
innerFunc(); // 100
위 코드에서 outer함수는 내부함수인 inner함수를 반환하고 생을 마감한다. outer함수는 실행 이후 콜스택(실행 컨텍스트 스택)에서 제거되었으므로, outer함수의 변수인 "x" 또한 유효하지 않게 되어 변수 "x"에 접근할 수 있는 방법이 없어보이지만, 위 코드의 실행 결과는 변수 "x"의 값인 100이다.
이처럼 내부함수가 자신을 포함하고 있는 외부함수보다 더 오래 유지되는 경우에 외부함수 밖에서 내부함수가 호출되더라도 외부함수의 지역 변수에 접근할 수 있는데, 이러한 함수를 클로저(Closure)라고 한다.
클로저란?
- 자신을 포함한 외부함수 밖에서 호출되어도 외부함수의 지역변수에 접근할 수 있는 함수
- 즉, 자신이 생성될 때의 환경(Lexical environment)을 기억하는 함수
클로저에 의해 참조되는 외부함수의 변수, 즉 위 코드에서 outer함수의 변수 "x"를 자유변수(Free variable)라고 한다. 외부함수가 이미 반환되었어도 외부함수 내의 변수는 이를 필요로 하는 내부함수가 하나라도 존재하는 경우에 계속 유지되며, 이 때 내부함수가 외부함수 안에 있는 변수의 복사본이 아닌 실제 변수에 접근한다는 것을 기억해야 한다.