console.log
[모던 자바스크립트 Deep Dive] 24 장 본문
24. 클로저
클로저
- 함수형 프로그래밍 언어(하스켈, 리스브, 얼랭, 스칼라) 에서 사용되는 중요한 특성
- ECMAScript에 정의가 나와있지 않음
- MDN에서는
클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.
라고 정의 -
const x = 1; function outerFunc() { const x = 10; function innerFunc() { console.log(x); // 10 } innerFunc(); } outerFunc();
- innerFunc 함수는 outerFunc 내부 중첩 함수이기 때문에 outerFunc의 x변수에 접근 가능 (렉시컬 스코프)
렉시컬 스코프
- 함수를 어디서 호출했는지
x
어디에 정의했는지o
-
const x = 1; function foo() { const x = 10; bar(); } function bar() { console.log(x); } foo(); // 1 bar(); // 1
함수 객체의 내부 슬롯 [[Environment]]
- 렉시컬 스코프가 가능하기 위해서는 상위 스코프(자신이 정의된 환경)을 기억해야 함
- 함수는 자신의 내부 슬록 [[Environment]] 에 상위 스코프의 참조를 저장
- 상위 스코프의 참조는 현재 실행 중인 실행 컨텍스트의 렉시컬 환경을 가리킴
- 함수 정의가 평가되어 함수 객체를 생성하는 시점은 상위 함수가 평가 또는 실행되고 있는 시점
- 함수 내부에서 정의된 함수 표현식은 외부 함수 코드가 실행되는 시점에 생성
-
함수 실행 컨텍스트 생성
-
함수 렉시컬 환경 생성
2-1. 함수 환경 레코드 생성
2-2. this 바인딩
2-3. 외부 렉시컬 환경에 대한 참조 결정 ([[Environment]] 에 저장된 렉시컬 환경의 참조가 할당됨)
-
클로저와 렉시컬 환경
-
const x = 1; // 1. function outer() { const x = 10; const inner = function () { console.log(x); }; // 2. return inner; } // outer 함수를 호출하면 중첩 함수 inner를 반환한다. // 그리고 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거된다. const innerFunc = outer(); // undefined 3. innerFunc(); // 10 4.
-
3에서 outer 함수를 호출하면 inner함수를 반환하고 생명주기 마감 → outer 함수의 실행 컨텍스트는 스택에서 제거
-
이때, 지역 변수 x도 생명 주기 마감되어 접근할 수 없어야 하지만
중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수 참조 가능
→ 이러한 중첩 함수를클로저
라고 한다. -
outer 함수의 실행 컨텍스트가 제거되지만 outer 함수의 렉시컬 환경은 남아있음 (누군가 참조 중인 공간은 가비지 컬렉션 대상 안됨 !)
-
상위 스코프의 어떤 식별자도 참조하지 않으면 클로저가 아님 !
-
function foo() { const x = 1; function bar() { debugger; console.log(x); } bar(); } foo();
- 외부 함수 foo 보다 bar의 생명 주기가 짧기 때문에 클로저라고 하지 않음
-
- 즉, 클로저는
중첩 함수가 상위 스코프의 식별자를 참조
하고 있고,외부 함수보다 생명 주기가 길 때
한정
클로저의 활용
- 상태를 안전하게 변경하고 유지
- 상태를 안전하게 은닉, 특정 함수만 상태 변경 허용
-
// 카운트 상태 변수 let num = 0; // 카운트 상태 변경 함수 const increase = function () { // 카운트 상태를 1만큼 증가시킨다. return ++num; }; console.log(increase()); // 1 console.log(increase()); // 2 console.log(increase()); // 3
- 오류 발생 가능성 있음
- 카운트 상태는 increase 함수 호출 전까지 변경되지 않고 유지되어야 함
- 카운트 상태는 increase 함수만 변경 가능해야 함
// 카운트 상태 변경 함수 const increase = function () { // 카운트 상태 변수 let num = 0; // 카운트 상태를 1만큼 증가시킨다. return ++num; }; // 이전 상태를 유지하지 못한다. console.log(increase()); // 1 console.log(increase()); // 2 console.log(increase()); // 3
- 카운트 상태를 increase 함수의 지역 변수로 변경
- increase 함수만이 변경 가능
- 하지만 이전 상태 유지 못함
// 카운트 상태 변경 함수 const increase = (function () { // 카운트 상태 변수 let num = 0; // 클로저 return function () { // 카운트 상태를 1만큼 증가시킨다. return ++num; }; })(); // 이전 상태를 유지하지 못한다. console.log(increase()); // 1 console.log(increase()); // 2 console.log(increase()); // 3
- 즉시 실행 함수가 호출되고 increase 변수에는 즉시 실행 함수가 반환한 함수가 할당됨
- 따라서 num 변수는 재차 초기화 될 일이 없고 외부에서 접근 불가
- 오류 발생 가능성 있음
'개발공부 > JavaScript' 카테고리의 다른 글
[AJAX] Client에서 Request를 전송하고 응답을 처리하는 시나리오 (0) | 2023.09.01 |
---|---|
[모던 자바스크립트 Deep Dive] 22 - 23 장 Self Quiz (0) | 2023.08.29 |
[모던 자바스크립트 Deep Dive] 22 - 23 장 (0) | 2023.08.28 |
[모던 자바스크립트 Deep Dive] 20 - 21 장 Self Quiz (0) | 2023.08.27 |
[모던 자바스크립트 Deep Dive] 20 - 21 장 (0) | 2023.08.26 |