"함수와 그 함수가 선언될 당시의 렉시컬 환경(Lexical Environment)의 조합"**을 말한다.
"함수가 생성될 때의 외부 변수 상태(환경)를 함께 기억하고 있는 함수" 라고 이해하면 된다.
function outer() {
let a = 1;
return function inner() {
return ++a;
};
}
const fn = outer();
console.log(fn()); // 2
console.log(fn()); // 3
전역 실행 컨텍스트 생성.
outer 실행 컨텍스트 생성.
outer 실행 컨텍스트에는 LexicalEnvironment가 있고, 그 안에는 EnvironmentRecord와 outerEnvironmentReference가 존재한다.
EnvironmentRecord에는 a = 1, inner: f가 담긴다.
outerEnvironmentReference에는 전역 실행 컨텍스트의 LexicalEnvironment가 담긴다. 여기에는 outer: f가 담겨져있다.
inner 실행 컨텍스트 생성.
inner 실행 컨텍스트에는 LexicalEnvironment가 있고, 그 안에는 EnvironmentRecord와 outerEnvironmentReference가 존재한다. EnvironmentRecord에는 아무 값도 존재하지 않는다.
outerEnvironmentReference에는 outer 실행 컨텍스트의 LexicalEnvironment를 참조한다. 여기에는 a = 1, inner: f가 담겨져있다.
inner 실행 컨텍스트 제거.
outer 실행 컨텍스트 제거.
전역 실행 컨텍스트 제거.
이 예제에서 outer()는 종료됐지만, 내부 함수 inner는 a를 계속 참조하고 있다.
이렇게 함수 종료 이후에도 변수 상태를 '기억'하고 있는 현상이 바로 클로저이다.
함수 실행 이후에도 변수 값을 유지할 수 있다
→ 일종의 데이터 저장소 역할
외부에서 내부 변수에 접근할 수 없게 만든다
→ 캡슐화, 정보 은닉 가능
함수를 반환하거나, 콜백으로 넘기는 구조에서 자주 사용된다
→ 특히 비동기 프로그래밍이나 이벤트 핸들링에서 강력함
함수 내부에서 내부 함수가 선언되고,
그 내부 함수가 외부 함수의 지역 변수를 참조하며,
그 내부 함수가 외부로 반환되거나 나중에 사용될 때
👉 즉, "내부 함수가 외부 변수에 접근하면서, 생명 주기를 늘릴 때" 클로저가 발생한다.
function user(_name) {
var _logged = true;
return {
get name() {return _name },
set name(v) { _name = v },
login() { _logged = true },
logout() { _logged = false },
get status() {
return _logged ? 'login' : logout;
},
}
};
var roy = user('상호');
console.log(roy.name);
출력결과 : '상호'
name 프로퍼티가 없지만, get name() {...}이 호출된다.
user('상호')의 user(_name) -> _name은 user 함수 내부에서 선언된 변수. 원래대로면 user 함수의 실행 컨텍스트가 종료되면서 같이 사라져야하지만. return 키워드롤 사용하여 해당 변수가 외부로 빠져나가기 때문에 변수는 사라지지않고 살아남게된다.
roy.name = '상우';
console.log(roy.name);
출력결과 : '상우'
name 프로퍼티가 없지만, set name(v) {...}이 호출된다.
roy._name = '상우';
console.log(roy.name);
출력결과 : '상호'
_name은 user 함수에서 생성되는 프로퍼티이지 user 함수로 인해 생성된 roy의 프로퍼티가 아니다. 따라서 roy 내부에 _name 변수가 새롭게 생성될 뿐이다.
console.log(roy.status);
출력결과 : true
user 함수 내부의 _logged 변수에 따라 결과값을 가져온다. _logged 변수도 마찬가지로 사라지지않고 살아남는 변수가 되는 것이다.
roy.logout();
roy.status = true;
console.log(roy.status);
출력결과 : false
status에는 setter가 없으므로 true 할당 명령은 무시된다. 외부에서 내부 변수에 접근하기 위한 방법이 제한된다는 것. 이를 캡슐화라고 한다.
함수가 호출되면 실행 컨텍스트가 생김
이 컨텍스트 안에는 LexicalEnvironment가 있음
내부 함수가 외부 변수에 접근하면 → 참조가 생김
이 참조가 남아있으면 실행 컨텍스트가 제거되지 않음
→ 변수는 계속 살아남음 → 클로저
클로저: 함수 + 외부 변수 참조 환경
목적: 변수 은닉, 캡슐화, 상태 저장
발생 조건: 내부 함수가 외부 변수를 참조하면서 반환됨
장점: 상태 유지, 정보 보호
주의점: 메모리 누수 가능성 (참조가 계속 남을 경우)