
실행 컨텍스트란
- 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
- 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트 구성
- 컨텍스트들을 순서대로 Call Stack에 쌓아 올림
- 최상위 컨텍스트와 관련 있는 코드들을 실행
- 전체 코드의 환경과 순서를 보장
실행 컨텍스트의 구성 방법
- 전역 공간 → 자동 실행
- eval() 함수 → 사용을 권장하지 않음
- 함수 → 가장 흔한 실행 컨텍스트 구성 방법
- 블록 →
{ }
로 둘러 쌓인 코드 내부. ES6 부터 지원
실행 컨텍스트와 콜스택
예제 코드
var a = 1;
function outer() {
function inner() {
console.log(a);
var a = 3;
}
inner();
console.log(a);
}
outer();
console.log(a);
- 실행 순서 : (1) → (5) → (3) → (2) → (4) → (6)
콜스택 변화

활성화 된 실행 컨텍스트의 수집 정보
- VariableEnvironment
- environmentRecord (snapshot)
- outerEnvironmentReference (snapshot)
- LexicalEnvironment
- environmentRecord
- outerEnvironmentReference
- ThisBinding - this 식별자가 바라봐야 할 대상 객체
VariableEnvironment
- 담기는 내용은 LexicalEnvironment와 같지만 최초 실행 시의 스냅샷을 유지
- 실행 컨텍스트 생성 시 VariableEnvironment에 먼저 정보를 담고, 그대로 LexicalEnvironment에 복사 한 후 주로 LexicalEnvironment를 활용
- 내부 구성 요소 : 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보가 선언 시점의 스냅샷으로 저장
- environmentRecord (snapshot)
- outerEnvironmentReference (snapshot)
LexicalEnvironment
- 내부 구성 요소 : VariableEnvironment와 동일하지만 변경 사항이 실시간으로 반영 됨
- environmentRecord
- outerEnvironmentReference
environmentRecord와 호이스팅(hoisting)
environmentRecord
- 현재 컨텍스트와 관련 된 코드의 식별자 정보들이 저장
- 컨텍스트를 구성하는 함수에 지정된 매개변수 식별자
- 선언한 함수가 있을 경우 그 함수 자체
- var로 선언 된 변수의 식별자
- 컨텍스트 내부 전체를 처음부터 끝까지 쭉 훑어나가며 순서대로 수집
- 전역 실행 컨텍스트
- 변수 객체 생성 대신 자바스크립트 구동 환경이 별도로 제공하는 전역 객체를 활용
- 브라우저의 window, Node.js의 global 객체 등
- 이들은 내장(native) 객체가 아닌 호스트(host) 객체로 분류
호이스팅의 등장
- 변수 정보를 수집하는 과정을 마쳤다면, 코드가 실행되기 전임에도 불구하고 자바스크립트 엔진은 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있게 됨
- '자바스크립트 엔진은 식별자들을 최상단으로 끌어 올려 놓은 다음 실제 코드를 실행하라'라고 생각해도 코드 해석에 문제가 없음
- 이러한 과정에서 호이스팅이라는 개념이 등장
호이스팅의 개념
- 호이스팅(hoisting) : hoist (끌어 올리다) + ~ing → 식별자들을 최상단으로 끌어 올려 놓자
- 변수 정보를 수집하는 과정을 더욱 이해하기 쉬운 방법으로 대체한 가상의 개념
- 자바스크립트 엔진이 실제로 끌어 올리지는 않지만 편의상 끌어 올리는 것으로 간주하자는 것
- 변수는 선언부와 할당부를 나눠 선언부만 끌어올리지만, 함수는 함수 전체를 끌어 올림
- 호이스팅이 끝난 상태에서의 함수 선언문은 (*)과 같이 함수명으로 선언한 변수에 함수를 할당한 것처럼 여길 수 있음
함수 선언문과 함수 표현식
- 함수 선언문 : 함수 정의부만 존재하고 별도의 할당 명령이 없는 것
- 함수 표현식 : 정의한 함수를 별도의 변수에 할당하는 것
- 익명 함수 표현식 : 함수명을 정의하지 않음
- 기명 함수 표현식 : 함수명을 정의함
- 외부에서 함수명으로 호출 불가능
- 내부에서 재귀함수를 호출하는 용도로 사용. 하지만 변수명으로도 호출 가능하여 굳이 쓸 필요는 없어 보임
- 호이스팅 시 변수로 취급되어 선언 부분만 끌어 올림
function a() { }
a();
var b = function () { }
b();
var c = function d() { }
c();
d();
- 함수 선언문이 코드 상단에 선언되어 있는 상태에서 동일한 이름의 함수 선언문이 하단에 중복되어 있을 경우 예기치 못한 동작이 발생할 우려가 있음
스코프, 스코프 체인, outerEnvironmentReference
스코프 체인
- 현재 스코프에 선언 된 식별자이 없으면 상위 스코프로 이동하여 검색
- 여러 스코프에서 동일한 식별자를 선언한 경우에는 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능
- 변수 은닉화 (Variable shadowing) : 상위 스코프에 선언되어 있지만, 현재 스코프에 이미 선언된 경우에는 값이 할당되어 있지 않다고 하더라도 현재 스코프의 변수를 우선으로 함
- 예제
var a = 1;
var outer = function() {
var inner = function() {
console.log(a);
var a = 3;
};
inner();
console.log(a);
}
outer();
console.log(a);
- (1) inner 함수 컨텍스트에는 a 식별자가 존재하지만 아직 값이 할당되지 않았기 때문에
undefined
을 출력
- (2) outer 함수 컨텍스트에는 a 식별자가 존재하지 않으므로, outerEnvironmentReference를 따라가서 전역 컨텍스트의 a에 들어 있는
1
을 출력
- (3) 전역 컨텍스트에는 a 식별자가 존재하고 값이 존재하므로
1
을 출력