1. 클로저

함수 outerFunc 내에서 내부함수 innerFunc가 선언되고 호출되었다. 이때 내부 함수 innerFunc는 자신을 포함하고 있는
외부함수 outerFunc의 변수 x에 접근할 수 있다. 이는 함수 innerFunc가 함수 outerFunc의 내부에 선언되었기 때문이다.

함수 innerFunc가 함수 outerFunc의 내부에 선언된 내부함수이므로 함수 innerFunc는 자신이 속한 렉시컬 스코퍼를 참조
할 수 있다.
내부함수 innerFunc가 호출되면 자신의 실행 컨텍스트가 실행 컨텍스트 스택에 쌓이고 변수 객체와 스코프 체인 그리고
this에 바인딩할 객체가 결정된다. 이때 스코프 체인은 전역 스코프를 가리치는 전역 객체와 함수 outerFunc의 스코프를
가리키는 함수 outerFunc의 활성 객체 그리고 함수 자신의 스코프를 가리키는 활성 객체를 순차적으로 바인딩한다.
내부함수 innerFunc가 자신을 포함하고 있는 외부함수 outerFunc의 변수 x에 접근할 수 있는 것, 다시 말해 상위 스코프에
접근할 수 있는 것은 렉시컬 스코프의 래퍼런스를 차례대로 저장하고 있는 실행 컨텍스트의 스코프 체인을 자바스크립트
엔진이 검색하였기에 가능한 것이다.
- innterFunc 함수 스코프(함수 자신의 스코프를 가리키는 활성 객체) 내에서 변수 x를 검색한다. 검색이 실패하였다.
- innerFunc 함수를 포함하는 외부 함수 outerFunc의 스코프(함수 outerFunc의 스코프를 가리키는 함수 outerFunc의
활성 객쳬)에서 변수 x를 검색한다. 검색이 성공하였다.

이번에는 내부함수 innerFunc를 함수 outerFunc 내에서 반환하도록 변경해 보자.
함수 outerFunc는 내부함수 innerFunc를 반환하고 생을 마감했다. 즉, 함수 outerFunc는 실행된 이후 콜스택에서 제거되
었으므로 함수 outerFunc의 변수 x 또한 더이상 유효하지 않게 되어 변수 x에 접근할 수 있는 방법은 달리 없어 보인다.
그러나 위 코드의 실행 결과는 변수 x의 값인 10이다.
자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부함수가 호출되더라도 외부
함수의 지역 변수에 접근할 수 있는데 이러한 함수를 클로저(Closure)라고 부른다.
클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에
서 호출되어도 그 환경에 접근할 수 있는 함수를 말한다. 이를 조금 더 간단히 말하면 클로저는 자신이 생성될 때의 환경
을 기억하는 함수다라고 말할 수 있겠다.
클로저에 의해 참조되는 외부함수의 변수 즉 outerFunc 함수의 변수 x를 자유변수라고 부른다.
2. 클로저의 활용
2.1 상태 유지
클로저가 가장 유용하게 사용되는 상황은 현재 상태를 기억하고 변경된 최신 상태를 유지하는 것이다.

- 즉시실행함수는 함수를 반환하고 즉시 소멸한다. 즉시실행함수가 반환한 함수는 자신이 생성됐을 때의 렉시컬 환경에 속한 변수 isShow를 기억하는 클로저다. 클로저가 기억하는 변수 isShow는 box 요소의 표시 상태를 나타낸다.
- 클로저를 이벤트 핸들러로서 이벤트 프로퍼티에 할당했다. 이벤트 프로퍼티에서 이벤트 핸들러인 클로저를 제거하지 않는 한 클로저가 기억하는 렉시컬 환경의 변수 isShow는 소멸하지 않는다. 다시 말해 현재 상태를 기억한다.
- 버튼을 클릭하면 이벤트 프로퍼티에 할당한 이벤트 핸들러인 클로저가 호출된다. 이때 .box요소의 표시 상태를 나타내는 변수 isShow의 값이 변경된다. 변수 isShiw는 클로저에 의해 참조되고 있기 때문에 유효하며 자신의 변경된 최신 상태를 계속해서 유지한다.
2.2 전역 변수의 사용 억제

스크립트가 실행되면 즉시실행함수가 호출되고 변수 increase에는 함수 function () { return ++counter;}가 할당된다.
즉시실행함수는 호출된 이후 소멸되지만 즉시실행함수가 반환한 함수는 변수 increase에 할당되어 inclease 버튼을
클릭하면 클릭 이벤트 핸들러 내부에 호출된다. 이때 클로저인 이 함수는 자신이 선언됐을 때의 렉시컬 환경인 즉시
실행함수의 스코프에 속한 지역변수 counter를 기억한다. 따라서 즉시실행함수의 변수 counter에 접근할 수 있고
변수 counter는 자신을 참조하는 함수가 소멸될 때까지 유지된다.
즉시실행함수는 한번만 실행되므로 increase가 호출될 때마다 변수 counter가 재차 초기화될 일은 없을 것이다.
'JavaScript' 카테고리의 다른 글
| [PoiemaWeb] Date 객체 (0) | 2023.03.22 |
|---|---|
| [PoiemaWeb] Math (0) | 2023.03.22 |
| [PoiemaWeb] this (0) | 2023.03.15 |
| [PoiemaWeb] 프로토타입 (0) | 2023.03.12 |
| [PoiemaWeb] 함수의 형태(즉시 실행, 내부, 재귀, 콜백) (0) | 2023.03.10 |