클로저 정리
클로저 클로저란 우선 자바 스크립트의 고유 개념은 아니다. 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서 사용되는 중요한 특성이다.
const x = 1;
function outerFunc() {
const x = 10;
function innerFunc() {
console.log(x); // 10
}
innerFunc();
}
outerFunc();
outerFunc 함수 내부에서 중첩 함수 innerFunc가 정의되고 호출된다. 이 때 중첩 함수 innerFunc의 상위 스코프는 외부 함수 outerFunc의 스코프이다. 따라서 중첩 함수 innerFunc 내부에서 나 자신을 포함하고 있는 외부 함수 outerFunc의 x 변수에 접근할 수 있다.
=> 이 같은 현상이 발생하는 이유는 자바스크립트가 렉시컬 스코프를 따르는 프로그래밍 언어이기 때문이다.
렉시컬 스코프 자바스크립트 엔진은 함수를 어디서 호출했는지가 아니라, 함수가 어디에 정의되어있는지에 따라 상위 스코프를 결정한다. 이를 렉시컬 스코프 ( 정적 스코프 )라 한다.
클로저의 정의
- MDN 정의 : 클로저는 함수와 그 함수가 선언된 환경과의 조합이다.
클로저와 렉시컬 환경 예제를 통해 살펴보자.
const x = 1;
function outer() {
const x = 10;
const inner = function() {console.log(x);};
return inner;
}
const innerFunc = outer();
innerFunc();
outer 함수를 호출하면 outer 함수는 중첩 함수 inner을 반환하고, 생명주기를 마감한다. 즉, outer 함수의 실행이 종료되면 outer 함수의 실행 컨택스트는 실행 컨택스트 스택에서 제거된다.
이때 outer 함수의 지역 변수 x 와 변수 값 10을 저장하고 있던 outer 함수의 실행 컨택스트가 제거되었으므로 outer 함수의 지역 변수 x 또한 생명 주기를 마갛만다. 따라서 outer 함수의 지역 변수 x는 더이상 유효하지 않게 되어 x 변수에 접근할 수 있는 방법은 없어보인다.
하지만, 다음 코드 값의 결과는 10이다. => 이미 생명주기가 종료되어 실행 컨택스트 스택에서 제거된 outer 함수의 지역 변수 x가 동작하고 있는 것이다.
이처럼 외부 함수보다 중첩 함수가 더 오래 유지되는 경우, 중첩 함수는 이미 생명주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이를 클로저라고 한다.
이를 활용한 장점으로는 다음과 같다.
- 데이터를 은닉할 수 있다.
- 함수 바깥에서는 직접 접근을 못하고, 클로저를 통해서만 내부 상태를 바꾸게 만들 수 있다.
- 전역 변수 사용을 줄이고 캡슐화에 도움이 된다.
- 상태를 유지할 수 있다.
- 일반 함수는 호출이 끝나면 지역 변수가 사라지는데, 클로저는 필요한 값을 계속 기억할 수 있다.