클로저란?
- 함수와 그 함수가 선언된 렉시컬 환경과의 조합
const x= 1;
function outerFunc(){
const x = 10;
function innerFunc(){
console.log(x); // 10
}
innerFunc();
}
outerFunc();
innerFunc의 상위 스코프는 outerFunc의 스코프
따라서 innerFunc 내부에서 자신을 포함하고 있는 outerFunc의 x 변수에 접근 가능
만약 innerFunc 함수가 outerFunc 함수의 내부에서 정의된 중첩 함수가 아니라면 innerFunc 함수를 outerFunc 함수의 내부에서 호출한다 하더라도 outerFunc 함수의 변수에 접근 불가
const x= 1;
function outerFunc(){
const x = 10;
innerFunc();
}
function innerFunc(){
console.log(x); // 1
}
outerFunc();
이 같은 현상이 발생하는 이유는 자바스크립트가 렉시컬 스코프를 따르는 프로그래밍 언어이기 때문임
렉시컬 스코프
렉시컬 스코프란, 자바스크립트 엔진이 함수를 어디서 호출했는지가 아니라 함수를 어디에 정의
했는지에 따라 상위 스코프를 결정하는 것
렉시컬 환경의 ‘외부 렉시컬 환경에 대한 참조’에 저장할 참조값, 즉 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)에 의해 결정됨
함수 객체의 내부 슬롯
함수는 자신이 호출되는 환경과 상관없이 자신이 정의된 환경, 즉 상위 스코프를 기억해야함
이를 위해 함수는 자신의 내부 슬롯
[[Environment]]에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장함
함수 객체의 내부 슬롯[[Environment]]에 저장된 현재 실행 중인 실행 컨텍스트의 렉시컬 환경의 참조가 바로 상위 스코프임
또한 자신이 호출됐을 때 생성될 함수 렉시컬 환경의 ‘외부 렉시컬 환경에 대한 참조’에 저장될 참조값임
함수 객체는 내부 슬롯 [[Environment]]에 저장한 렉시컬 환경의 참조, 즉 상위 스코프를 자신이 존재하는 한 기억함
클로저와 렉시컬 환경
외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있는데, 이러한 중첩 함수를 클로저
라고 부름
outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거되지만 outer 함수의 렉시컬 환경까지 소멸하는 것은 아님
클로저는 중첩 함수가 상위 스코프의 식별자를 참조하고 있고 중첩 함수가 외부 함수보다 더 오래 유지되는 경우에 한정하는 것이 일반적임
클로저의 활용
클로저는 상태를 안전하게 변경하고 유지하기 위해 사용함
다시 말해, 상태가 의도치 않게 변경되지 않도록 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하기 위해 사용함
QUIZ
- 클로저의 동작 원리를 설명해주세요
- 외부 함수의 실행 컨텍스트는 함수가 호출될때 콜스택에 쌓였다가 함수의 실행이 종료되면 콜스택에서 제거된다.외부 함수의 렉시컬 환경은 클로저의 내부 슬롯에 의해 참조되고 있어 가지비 컬렉션의 대상이 되지 않는다. 가비지 컬렉터는 누군가가 참조하고 있는 메모리 공간을 함부로 해제하지 않는다.
- 이때 외부 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거되지만 외부 함수의 렉시컬 환경까지 소멸하는 것이 아니다.
- 클로저는 실행 컨텍스트가 갖고 있는 렉시컬 환경 객체를 참조한다.
- 클로저는 왜 필요한가요?
- 자바스크립트에서 private 접근 제한자를 지원하지 않기 때문이다.
- 상태가 의도치 않게 변경되지 않도록 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하여 상태를 안전하게 변경하고 유지하기 위해 클로저가 필요하다.
- 클로저란 무엇인지 설명해주세요
- 함수와 그 함수가 선언된 렉시컬 환경과의 조합으로, 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 이미 생명 주기가 종료한 외부 함수의 변수를 참조하는 중첩 함수를 클로저라고 한다.
- 클로저와 렉시컬 스코프의 관계를 설명해주세요
- 클로저는 외부 함수 안에서 정의되는 함수다. 따라서 외부 함수에서 코드 평가가 진행되면 함수 선언부가 정의될 때 중첩 함수인 클로저의 함수 객체가 생성된다.
- 렉시컬 스코프는 함수가 정의되는 시점에서 생성되기 때문에, 자신의 렉시컬 환경을 기억할 수 있다. 이러한 특징으로 인해서 클로저가 외부 함수 밖에서 호출되더라도 외부함수의 식별자를 참조할 수 있게 된다.
- 함수 객체의 내부 슬롯 “[[Environment]]”와 렉시컬 환경의 “외부 렉시컬 환경에 대한 참조( Outer Lexical Environment Reference)”에 각각 어떤 값이 어느시점에 저장되는지 설명해주세요.
- 외부 함수가 평가되어 함수 객체를 생성할때:
- 현재 실행 중인 실행 컨텍스트의 렉시컬 환경, 즉 전역 렉시컬 환경을 외부 함수 객체의 내부 슬롯에 상위 스코프로서 저장한다.
- 실행 컨텍스트의 렉시컬 환경 참조값이 함수 객체의 내부 슬롯 [[Environment]] 에 저장
- 외부 함수를 호출할때:
- 외부 함수의 렉시컬 환경이 생성되고 앞서 외부 함수 객체의 내부 슬롯에 저장된 전역 렉시컬 환경을 외부 함수 렉시컬 환경의 ‘외부 렉시컬 환경에 대한 참조’에 할당한다.
- [[Enviroment]] 값이 “외부 렉시컬 환경에 대한 참조값”에 저장됨. 결과적으로 [[Enviroment]]와 “외부 렉시컬 환경에 대한 참조값”은 모두 상위 스코프의 렉시컬 환경 참조값을 저장한다.
- 외부 함수가 평가되어 함수 객체를 생성할때:
'etc' 카테고리의 다른 글
230615 (0) | 2023.06.15 |
---|---|
자바스크립트 딥다이브 - 프로토타입 (0) | 2023.04.21 |
원티드 프리온보딩 인턴십 9차 후기 (프론트엔드 부트캠프, 취업연계, JavaScript & React) (0) | 2023.04.05 |
자바스크립트로 todo-list 만들기 (0) | 2022.12.07 |
12/7 (0) | 2022.12.07 |