MDN에서 클로저의 정의 : 클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다
자바스크립트 엔진은 함수를 어디서 호출했는지가 아닌 어디에 정의했는지에 따라 상위 스코프를 결정한다
= 렉시컬 스코프
= 렉시컬 환경의 '외부 렉시컬 환경에 대한 참조'에 저장할 참조값, 즉 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)에 의해 결정된다
함수는 정의된 환경과 호출된 환경이 다를 수 있음
호출되는 위치와 상관없이 자신이 정의된 환경을 알아야 렉시컬 스코프가 가능
이를 위해 함수는 자신의 내부 슬롯 [[Environment]]에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장함
[[Environment]]에는 현재 실행 중인 실행 컨텍스트의 렉시컬 환경의 참조가 저장됨
함수 객체의 내부 슬롯 [[Environment]]에 저장된 현재 실행 중인 실행 컨텍스트의 렉시컬 환경의 참조가 상위 스코프이고,
또한 해당 함수가 호출되었을 때 생성될 함수 렉시컬 환경의 '외부 렉시컬 환경에 대한 참조'에 저장될 값이기도 하다
함수는 내부 슬롯 [[Environment]]에 저장한 렉시컬 환경의 참조(상위 스코프)를 자신이 존재하는 한 기억한다
const x = 1;
function foo(){
const x = 10;
bar();
}
function bar(){
console.log(x);
}
foo();
bar();
foo 함수를 호출하여 foo 함수 내부에서 bar 함수가 호출되었을 때 실행 컨텍스트는

const x = 1;
function outer(){
const x = 10;
const inner = function(){
console.log(x);
}
return inner;
}
const innerFunc = outer();
innerFunc(); // 10
외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기를 마감한 외부 함수의 변수를 참조할 수 있다
이러한 중첩 함수를 클로저라고 한다
outer 함수가 실행되면

outer 함수가 종료되면

outer 함수의 실행 컨텍스트는 콜 스택에서 제거되지만 outer 함수의 렉시컬 환경은 소멸되지 않음
outer 함수의 렉시컬 환경은 inner 함수의 [[Environment]] 내부 슬롯에 의해 참조되고 있고, inner 함수는 전역 변수 innerFunc에 의해 참조되고 있으므로 가비지 컬렉션의 대상이 X
가비지 컬렉터는 참조하고 있는 메모리 공간을 해제하지 않음

클로저는 중첩 함수가 상위 스코프의 식별자를 참조하고 있고 중첩 함수가 외부 함수보다 더 오래 유지되는 경우에 한정
중첩 함수가 외부 함수보다 오래 유지되어도 상위 스코프의 식별자를 참조하지 않으면 클로저 X
자유 변수 : 클로저에 의해 참조되는 상위 스코프의 변수
클로저 : 함수가 자유 변수에 대해 닫혀있다 = 자유 변수에 묶여있는 함수
상태를 안전하게 변경하고 유지하기 위해 사용
= 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용
const counter = (function(){
let num = 0;
return {
increase(){
return ++num;
},
decrease(){
return num>0 ? --num : 0;
}
};
}());
console.log(counter.increase()); // 1
console.log(counter.increase()); // 2
console.log(counter.decrease()); // 1
console.log(counter.decrease()); // 0