LexicalEnvironment
를 기억하고 이를 통해 외부 변수에 접근할 수 있습니다.주1. 하나의 예외는 new Function syntax 입니다.
모든 함수는 선언될 때, 함수 선언시의 실행 컨텍스트의 LexicalEnvironment
의 참조값을 내부 프로퍼티 [[Environment]]
에 저장해둡니다. [[Environement]]
참조는 한번 설정된 후 영원히 기억됩니다.
함수가 실행되면, 호출 직후 로컬 변수와 함수의 매개변수를 저장하기 위해 실행 컨텍스트 및 새로운 LexicalEnvironment
가 자동으로 생성됩니다.
함수 실행시 새로 생성된 LexicalEnvironment
는 함수의 [[Environment]]
에 저장된 LexicalEnvironment
를 외부 LexicalEnvironment
로 참조합니다.
코드가 변수에 접근할 때 현재 속한 실행 컨텍스트의 LexicalEnvironemnt
를 먼저 찾아본 후, 변수가 존재하지 않으면 LexicalEnvironment
의 외부 LexicalEnvironment
를 찾으며, 최상단의 global Lexical Environment까지 이어집니다. 변수를 찾지못한다면 스트릭트 모드에서는 예외가 발생합니다.
일반적으로 함수 호출이 종료되면 활성화된 실행 컨텍스트의 LexicalEnvironment
는 모든 변수와 함께 메모리에서 제거됩니다. 왜냐하면 LexicalEnvironment
에 대한 참조가 없기 때문이죠. 다른 자바스크립트 객체와 같이, Lexical Enviroment
에 도달가능할 때만 가비지 컬렉션의 대상에서 제외됩니다.
그러나 함수 호출이 종료된 후에도 여전히 해당 LexicalEnvironment
에 도달 가능한 중첩 함수가 존재한다면, 이때는 이 중첩함수의 [[Environment]]
프로퍼티에 외부 함수 Lexical Environment의 참조값을 가지고 있습니다. 이 경우, 함수가 종료되더라도 LexicalEnvironment
에 여전히 도달가능하므로 해당 LexicalEnvironment
는 살아있게 됩니다.
이론적으로는 함수가 살아있다면, LexicalEnvironment
가 살아있다면 모든 외부 변수들은 살아남습니다. 하지만 실무에서는, JS엔진이 최적화를 수행합니다. JS엔진은 변수의 사용을 분석해서 외부 변수가 사용되지 않는 것이 명백하다면 해당 외부 변수는 메모리에서 제거합니다.
따라서, 외부 함수가 종료되어 외부 함수의 실행 컨텍스트가 제거되어도 외부 함수의 LexicalEnvironment
는 내부 함수에서 [[Environment]]
를 통해 접근이 가능하므로 메모리에서 제거되지 않아, 내부 함수(클로저)를 호출시에도 함수 선언시의 환경을 참조할 수 있습니다.
Lexical Environment
를 가집니다. Lexical Environment
는 명세에서만 이론적으로 존재하는 객체로서, 실제로 코드에서 이 객체에 접근하거나 조정할 수 없습니다.Lexical Environment
는 두개의 파트로 구성되어 있습니다.Environment Record
: 모든 로컬 변수를 프로퍼티로 저장하는 객체(this 값 등의 다른 정보도 저장하고 있다)outer
: 함수가 선언될 때의 LexicalEnvironment
에 대한 참조값Lexical Environment
의 특별한 내부 객체인 Environment Record
의 프로퍼티입니다.Lexical Environment
를 생성합니다. Environment Record
는 어떠한 식별자가 존재하는지에 대해서만 관심이 있고, 식별자의 값에는 관심이 없습니다. 따라서 최초 생성된 Environment Record
의 let/const로 선언한 변수의 상태는 <unintialized>
이고, 실제로 선언되기 전까지는 접근할 수 없습니다. 이때를 흔히 Temporal Dead Zone
에 변수가 존재한다고 표현합니다.Lexical Environment
가 생성되면서 바로 initialized
되어 바로 사용할 수 있습니다.https://javascript.info/closure#lexical-environment
https://humorous-octagon-753.notion.site/b1fdfd69ce0e41dfb16bab7c570972b3
JS에서 모든 함수는 자연적으로 클로져입니다. 이 말이 이해되는 날이 오네요. 좋은 정리 감사합니다. 👍