렉시컬 환경 : 스크립트 전체, 실행중인 함수, 코드블록 등은 자신만의 렉시컬 환경을 갖는다. 렉시컬 환경은 환경레코드, 외부렉시컬 환경으로 구성된다.
렉시컬 환경에서 모든 지역변수를 프로퍼티로 저장하고 있는 객체이다. this, 함수일 경우 매개변수도 포함된다.
function add(a, b) {
let name = 'Pete'
}
add()
환경레코드에 {name: 'Pete', a: undefined } 이런식으로 저장되어 있다.
현재 렉시컬 환경보다 더 상위의 렉시컬 환경이다. 스크립트는 최상위 렉시컬 환경이며 스크립트 내에 호출된 함수나 코드블록은 외부렉시컬 환경으로 스크립트 렉시컬 환경을 참조한다.
렉시컬 환경이 만들어질 때 Environment라는 숨김 프로퍼티가 만들어진다. 프로퍼티에는 외부렉시컬 환경이 저장되어있으며 지역내에서 참조할 값이 없을 경우 프로퍼티에 접근하여 외부 렉시컬 환경을 참조하게되는데 값이 없을 경우 최상위 렉시컬 환경까지 검색하게 되는 체이닝 과정이 일어난다. 그렇기 때문에 모든함수는 클로저라고 할 수 있다.
function makeCounter() {
let count = 0;
return function() {
return count++;
};
}
let counter = makeCounter();
console.log(counter()); // 0
console.log(counter()); // 1
console.log(counter()); // 2
console.log(makeConter()()); // 0
console.log(makeConter()()); // 0
console.log(makeConter()()); // 0
위 중첩 함수에서 함수 호출을 변수에 저장해두고 쓰면 하나의 렉시컬 환경이 만들어 진다. 중첩된 함수를 여러번 호출할 때에 하나의 makeCounter() 함수를 외부 렉시컬 환경으로 참조하므로 count가 증가된 값들이 반영된다.
하지만 변수에 저장해두고 쓰지 않고 함수를 3번 호출한 경우 3개의 고유한 렉시컬 환경(makeCounter)이 만들어지고 중첩된 함수는 각각의 서로다른 외부렉시컬 환경(makeCounter)을 참조하기 때문에 위와 같은 콘솔 결과가 나타난다.
0이 출력되는 이유는 후위 증가 연산자이기 때문