MDN에서는 클로저를 다음과 같이 정의합니다.
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).
(번역) 클로저는 주변 상태 (렉시컬 환경)에 대한 참조와 함께 번들로 묶인 (포함된) 함수의 조합입니다.
위 정의만으로는 이해가 쉽게 되지 않습니다. 다음 예제를 보겠습니다.
const a = 1;
function outerFunc() {
const a = 2;
function innerFunc() {
console.log(a); // 2
}
innerFunc();
}
outerFunc();
outerFunc 함수 내부에서 중첩 함수 innerFunc를 정의하고 호출하였습니다. 이때 중첩 함수 innerFunc의 상위 스코프는 외부 함수 outerFunc의 렉시컬 환경입니다. 그렇기 때문에 a변수를 참조할 수 있습니다.
즉, innerFunc 렉시컬 환경의 외부 렉시컬에 대한 참조에 outerFunc의 렉시컬 환경이 바인딩됩니다. 이렇게 렉시컬 스코프를 통해 참조 가능한 현상이 위 번역에서 '주변 상태 (렉시컬 환경)에 대한 참조와'에 해당되는 부분입니다.
내부 슬롯 [[Environment]]
함수가 정의된 환경과 호출되는 환경은 다를 수 있습니다. 따라서 함수는 자신이 호출되는 환경과 상관없이 자신이 정의된 환경, 즉 상위 스코프를 기억해야 합니다. 이때 함수는 [[Environment]] 내부 슬롯에 자신이 정의된 환경(현재 실행 중인 실행 컨텍스트의 환경)을 저장합니다. 이때 자신이 정의된 환경이 상위 스코프 환경이 되는 것입니다. 이 [[Environment]] 내부 슬롯에 참조된 환경이 함수가 호출되었을 때 생성되는 함수 렉시컬 환경의 외부 렉시컬 환경에 대한 참조'에 저장될 참조값입니다.
정리하면 함수는 [[Environment]] 내부 슬롯에 상위 스코프를 저장합니다.
위 예제에서는 innerFunc의 [[Environment]] 내부 슬롯에 outerFunc 함수의 렉시컬 환경 참조값이 저장됩니다.
클로저와 렉시컬 환경
const a = 1;
function outer() {
const a = 2;
const inner = function () {
console.log(a);
};
return inner;
}
const innerFunc = outer();
innerFunc(); // 2
outer 함수를 호출하면 중첩함수 inner를 반환하고 생명 주기를 마감합니다. outer 함수의 실행 컨텍스트가 실행 컨텍스트 스택에서 팝된 것입니다. 그러나 inner의 [[Environment]] 내부 슬롯에 outer 함수의 렉시컬 환경이 참조되고 있기 때문에 outer 함수의 렉시컬 환경은 삭제되지 않습니다. 그렇기 때문에 외부 함수가 생명 주기를 마감했어도 중첩 함수가 호출할 때 외부 함수의 지역 변수에 접근할 수 있는데, 이러한 함수들의 조합을 클로저라 부릅니다.
클로저 활용
클로저는 상태를 안전하게 변경하고 유지하기 위해 사용합니다. 상태를 안전하게 은닉하고 특정함수에게만 상태 변경을 허용하기 위해 사용할 수 있습니다.
'JAVASCRIPT > 자바스크립트 이론' 카테고리의 다른 글
쿠키 / 세션 / 로컬스토리지 / 세션스토리지 (0) | 2021.02.01 |
---|---|
브라우저 렌더링 과정 (0) | 2021.01.31 |
실행 컨텍스트란 (2) | 2021.01.28 |
자바스크립트에서 this는 어떻게 바인딩될까 (5) | 2021.01.26 |
프로토타입이란 (0) | 2021.01.26 |