
앞선 포스팅에서 자바스크립의 기초적인 개념들을 살펴봤다. 이번 포스팅에서는 JavaScript의 핵심 메커니즘 중 하나인 '실행 컨텍스트'를 학습하겠다. 이 개념은 JavaScript 코드가 어떻게 해석되고 실행되는지에 대한 근본적인 이해를 제공하며, 앞서 논의된 모든 주제들과 깊이 연결되어 있다. 실행 컨텍스트를 통해, 우리는 JavaScript의 실행 흐름을 보다 명확히 파악하고, 코드가 왜 그렇게 작동하는지에 대한 더욱 심오한 이해에 도달할 수 있다 🫡 ❣️ 🧗🏻♀️
스택과 큐

실행 컨텍스트는 스택의 구조를 따른다.
콜 스택
다음 예시코드는 호이스팅에 의해 다음과 같이 동작한다.
var a = 1;
function outer() {
function inner() {
console.log(a); //(1) undefined
var a = 3;
}
inner();
console.log(a); //(2) 1
}
outer();
console.log(a); //(3) 1
var a;선언됨outer() 호출 후 outer() 내부에 있는 inner() 호출됨var a; 선언됨할당 전 console.log(a); 는 초기화만 된 상태이므로 undefinedinner() 스코프 를 빠져나간 console.log(a); 는 전역 스코프 var a=1; 에 따라 1이 출력됨outer() 스코프를 빠져나간 a도 동일한 동작으로 1 출력만약 let,const로 선언하면? 🤔
let, const는 선언과 초기화가 독립적으로 발생하므로 TDZ에 걸려 참조 에러가 발생한다.
let a = 1;
function outer() {
function inner() {
console.log(a); //(1) ReferenceError
let a = 3;
}
inner();
console.log(a);
}
outer();
console.log(a);
이를 콜스택에서 실행 컨텍스트가 어떻게 push, pop 되는지 시각화해보면 다음과 같다.

즉, 콜 스택 최상단에 위치한 컨텍스트가 현재 실행중인 컨텍스트임을 알 수 있다.
그렇다면 현재 실행 중인 컨텍스트는 어떻게 동작할까? 그 내부를 해부해보자.🚗 💨 💨
콜 스택에서 현재 실행 중인 컨텍스트, 즉 최상단에 위치한 실행 컨텍스트에는 VariableEnvironment, LexicalEnvironment, 그리고 this 바인딩과 같은 중요한 정보들이 담겨 있다. 이 정보들은 현재 실행 중인 코드가 어떻게 동작할지를 결정하는 데 핵심적인 역할을 한다.
VariableEnvironment 와 LexicalEnvironment
변수와 함수 선언을 저장하는 데 사용된다. 이 두 환경은 실행 컨텍스트가 생성될 때 초기화되지만, LexicalEnvironment는 실행 도중에도 업데이트될 수 있다. 이는 let과 const로 선언된 변수들이나 함수 표현식이 실행 흐름에 따라 달라지기 때문입니다. VariableEnvironment는 주로 실행 컨텍스트 생성 시의 상태를 반영하며, 이후 변경되지 않는다.
LexicalEnvironment의 역할
실행 컨텍스트에 속한 코드가 실행될 때 현재의 변수와 함수 선언에 대한 접근을 제어한다. LexicalEnvironment는 또한 외부 환경에 대한 참조도 포함하고 있어, 스코프 체인을 형성하고 변수를 찾을 때 이 스코프 체인을 따라서 검색할 수 있게 한다. ❗️컨텍스트를 구성하는 환경 정보들을 모아놓았다고 생각하면 쉽다❗️
실행 전 정보들을 VariableEnvironment와 LexicalEnvironment에 저장해놓는다는 것을 알게되었다. 그렇다면 우리가 지금까지 강조한 자바스크립트만의 고유한 특징인 호이스팅도 이러한 환경들에 저장되는 것일까? 코드 흐름에 따라 정보를 업데이트하는 LexicalEnvironment를 살펴보자.
environmentRecord는 실행 컨텍스트의 LexicalEnvironment 구성 요소 중 하나로, 해당 스코프 내에서 선언된 모든 식별자(변수, 함수, 매개변수 등)와 그 값들을 저장한다. ❗️ 즉, 호이스팅 또한 LexicalEnvironment 그 중에서도 environmentRecord에 저장한다 ❗️
지금까지의 개념들로 실행 컨텍스트에 담기는 정보들을 도식화해보자.

위의 예시 코드를 기반으로 시각화했고, inner() 실행 컨텍스트가 활성화 된 시점이다.
호이스팅과 할당, 외부참조의 정보가 각각 어디에 담기는지 확인해보았다.
마지막으로 호이스팅의 예제 코드를 보면서 오늘 포스팅을 마무리하겠다.
👩🏼💻 개발자 관점
function a() {
console.log(b); // [Function: b]
var b = 'bbb';
console.log(b); // bbb
function b() {}
console.log(b); // bbb
}
a();
⚙️ 엔진 관점
function a() {
var b;
function b() {}
console.log(b); // [Function: b]
var b = 'bbb';
console.log(b); // bbb
console.log(b); // bbb
}
a();
함수 a()가 호출되면, JavaScript 엔진은 해당 함수에 대한 새로운 실행 컨텍스트를 생성.자신만의 VariableEnvironment와 LexicalEnvironment를 갖음.함수 선언(function b() {})과 변수 선언(var b;) 모두 실행 컨텍스트의 환경 레코드에 호이스팅됨.높은 우선순위를 갖기 때문에, 초기 메모리 상태에서 b는 함수 b()를 가리킴. b는 함수 객체를 참조함.var b = 'bbb'; 코드가 실행되면서, 변수 b에 문자열 'bbb'가 할당됨.문자열 'bbb'로 업데이트됨.문자열 값을 가지게 됨.이미 호이스팅 처리 되었으므로, 이후의 코드 실행에는 영향을 미치지 않음.종료되면, a()의 실행 컨텍스트는 콜 스택에서 제거됨.