자바스크립트 엔진은 함수를 어디에 정의했는지에 따라 상위 스코프를 결정하고 이를 렉시컬 스코프라고 함
렉시컬 환경의 "외부 렉시컬 환경에 대한 참조"에 저장할 참조값, 즉 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)에 의해 결정됨
함수 객체의 내부 슬롯 [[Environment]]
함수는 자신의 내부 슬롯 [[Environment]]에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장함
함수는 자신의 내부 슬롯 [[Environment]]에 저장한 상위 스코프를 자신이 존재하는 한 기억함
함수 렉시컬 환경의 구성 요소인 외부 렉시컬 환경에 대한 참조에는 함수는 자신의 내부 슬롯 [[Environment]]에 저장된 렉시컬 환경의 참조가 할당됨!
클로저와 렉시컬 환경
외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있음
이러한 중첩 함수를 클로저 라고함
클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합
const x = 1;
function outer() {
const x = 10;
const inner = function () { console.log(x);};
return inner;
}
// outer 함수를 호출하면 중첩 함수 inner를 반환
// 그리고 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 pop 되어 제거됨
const innerFunc = outer();
innerFunc(); // 10;
outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거되지만 outer 함수의 렉시컬 환경까지 소멸되는 것은 아님
outer 함수의 렉시컬 환경은 inner 함수에 의해 참조되고 있고, inner 함수 또한 innerFunc에 의해 참조되고 있으므로 가비지 컬렉션의 대상이 되지 않기 때문
클로저의 활용
클로저는 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하기 위해 사용함
외부 상태 변경이나 가변 데이터를 피하고 불변성을 지향하는 함수형 프로그래밍에서 부수 효과를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이기 위해 클로저는 적극적으로 사용됨
const counter = (function() {
let num = 0;
return {
increase() {
return num++;
},
decrease() {
return num > 0 ? --num : 0;
}
};
}());
캡슐화와 정보 은닉
캡술화 : 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것
정보 은닉
캡슐화를 객체의 측정 프로퍼티나 메서드를 감출 목적으로 사용할 때
외부에 공개할 필요가 없는 구현의 일부를 외부에 공개되지 않도록 감추어 적절치 못한 접근으로부터 객체의 상태가 변경되는 것을 방지해 정보 보호