javaScript/js.closure

클로저(closure)

클로저는 자바스크립트 고유의 개념이 아니므로 ECMAScript 사양에 클로저의 정의가 등장하지 않는다.
클로저는 함수와 그 함수가 선언된 렉시컬 환경(Lexical environment)과의 조합이다.

1. 렉시컬 스코프

자바스크립트는 함수를 어디서 호출했는지가 아니라 어디에 정의했는지에 따라 상위 스코프를 결정한다. 이를 렉시컬 스코프(정적 스코프라)라한다.

렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장할 참조값, 즉 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)에 의해 결정된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
const x = 1;

function foo() {
const x = 10;
bar ();
}

function bar() {
console.log(x);
}

foo(); // 1
bar(); // 1
  • foo, bar 함수는 모두 전역에서 정의된 전역 함수
  • 두 함수의 상위 스코프는 전역이다.
  • 스코프의 실체는 실행 컨텍스트의 렉시컬 환경이다.
  • 렉시컬 환경은 자신의 외부 렉시컬 환경에 대한 참조(Outer Lexical Environment Reference)를 통해 상위 렉시컬 환경과 연결된다. 이것이 스코프 체인
  • 함수의 상위 스코프를 결정한다? -> 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장할 참조값을 결정한다.

2. 함수 객체의 내부 슬롯 [[Environment]]

  • 함수는 자신의 내부슬롯 [[Environment]]에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장한다.
  • 함수 정의가 평가되어 함수 객체를 생성할 때, 자신이 정의된 위치에 의해 결정된 상위 스코프의 참조를 함수 객체 자신의 내부슬롯 [[Environment]]에 저장한다.
  • 이때 자신의 내부슬롯 [[Environment]]에 저장된 상위 스코프의 참조는 현재 실행 중인 실행 컨텍스트의 렉시컬 환경을 가리킨다.
  • 함수 객체의 내부슬롯 [[Environment]]에 저장한 현재 실행 중인 실행 컨텍스트의 렉시컬 환경의 참조가 바로 상위 스코프이다.
    자신이 호출되었을 때 생성될 함수 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장될 참조값이다.
  • 함수 객체는 내부슬롯 [[Environment]]에 저장할 렉시컬 환경의 참조, 즉 상위 스코프를 자신이 존재하는 한 기억한다.

3. 클로저와 렉시컬 환경

1
2
3
4
5
6
7
8
9
10
11
12
const x = 1;

function outer() {
const x = 10;
const inner = function () {
console.log(x);
};
return inner;
}

const innerFunc = outer();
innerFUnc(); //10
  • outer 함수를 호출하면 outer는 중첩함수 inner 함수를 반환하고 생명주기를 마감
    (outer의 호출이 종료하면 함수 outer의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거)
  • 이때 함수 outer의 지역 변수 x와 변수값 10을 저장하고 있는 함수 outer 실행
    컨텍스트가 제거 되었으므로 함수 outer의 지역 변수 x 또한 생명 주기를 마감
  • 함수 outer의 지역 변수 x는 더이상 유효하지 않게 되어 변수 x에 접근할 수 있는 방법이 없어보임
  • 그러나 코드의 실행 결과는 x의 값인 10 이러한 함수를 클로저라..한다..
  • 자신의 상위 스코프를 기억하고 있기 때문이다.
  • inner 함수는 자신이 평가될 때 자신이 정의된 위치에 의해 결정된 상위스코프를
    [[Environment]] 내부슬롯에 저장한다. 이때 저장된 상위 스코프는 함수가 존재하는 한 유지된다.
  • outer 함수의 렉시컬 환경은 inner 함수의 [[Environment]] 내부슬롯에 의해 참조되고 있고 inner 함수는 전역 변수 innerFunc에 의해 참조되고 있으므로 가비지 컬렉션의 대상이 되지 않는다. (가비지 컬렉터는 참조되고 있는 메모리공간을 해제하지않는다.)

4. 클로저의 활용

클로저는 상태를 안전하게 유지하기 위해 사용한다. 상태가 의도치 않게 변경되지 않도록 안전하게 은닉한다.
이전 상태를 기억하다가 상태가 변경되면 최신 상태(state)를 유지한다.

….

You forgot to set the qrcode for Alipay. Please set it in _config.yml.
You forgot to set the qrcode for Wechat. Please set it in _config.yml.
You forgot to set the business and currency_code for Paypal. Please set it in _config.yml.
You forgot to set the url Patreon. Please set it in _config.yml.
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×