실행 컨텍스트란?
실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
실행 컨텍스트 실행
- 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보를 모아서 컨텍스트를 구성한다
- 동일한 환경: 함수 실행, 전역공간, eval()
- 컨텍스트를 콜 스택에 쌓아올린다
- 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행한다
실행 컨텍스트와 콜 스택
var a = 1;
function outer() {
function inner() {
console.log(a);
var a = 3;
}
inner();
console.log(a);
}
outer();
console.log(a);

- 전역 컨텍스트가 콜 스택에 담긴다
- 전역 컨텍스트: 자바스크립트 파일이 열리는 순간 활성화
- outer 함수 호출 -> outer 실행 컨텍스트가 콜 스택에 담긴다
- 전역 컨텍스트 관련 코드 일시중단 && outer 함수 내부 코드 순차적으로 실행
- inner 함수 호출 -> inner 실행 컨텍스트가 콜 스택에 담긴다
- outer 컨텍스트 관련 코드 일시중단 && inner 함수 내부 코드 순차적으로 실행
- inner 함수 종료 -> inner 실행 컨텍스트 콜 스택에서 제거
- outer 컨텍스트가 콜 스택 맨 위 -> 중단된 코드 다음 줄부터 이어서 실행
- outer 함수 종료 -> outer 실행 컨텍스트 콜 스택에서 제거
- 전역 컨텍스트가 콜 스택 맨 위 -> 중단된 코드 다음 줄부터 이어서 실행
- 전역 공간 함수 종료 -> 콜 스택에는 아무것도 없이 종료
그렇다면 왜 inner의 a는 undefined일까? 실행 컨텍스트 객체에 대해 더 자세히 알아보자

Variable Environment
- 최초 실행 시 스냅샷 유지
- 실행 컨텍스트를 생성할 때 Variable Environment에 정보를 먼저 담음 -> 이를 그대로 복사해 Lexical Environment 생성
Lexical Environment
environment Record와 호이스팅
- environment Record: 현재 컨텍스트와 관련된 코드의 식별자 정보 저장
- 컨텍스트 내부 전체를 처음부터 끝까지 훑어나가면 순서대로 수집
호이스팅
호이스팅, 코드가 실행되기 전에 자바스크립트 엔진이 이미 해당 환경에 속한 코드의 변수명을 알고 있다
- 자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다
- 변수를 호이스팅할 때 변수명만 끌어올리고 할당 과정은 원래 자리에서
호이스팅 규칙에 따라 아래와 같이 출력된다
function a (x) {
console.log(x);
var x;
console.log(x);
var x = 2;
console.log(x);
}
a(1);
function a () {
console.log(b);
var b = 'bbb';
console.log(b);
function b () { }
console.log(b);
}
a();
함수 선언문과 함수 표현식
function a () {}
var b = function () {}
var c = function d () {}
c();
d();
- 함수 선언문은 함수 전체를 호이스팅하지만, 함수 표현식으 변수 선언부만 호이스팅한다
함수 선언문의 위험성
전역 컨텍스트가 활성화될 때 전역공간에 선언된 함수들이 모두 가장 위로 끌어올려진다. 동일한 변수명에 서로 다른 값을 할당할 경우 나중에 할당한 값이 먼저 할당한 값을 덮어씌운다.
스코프, 스코프 체인, outerEnvironmentReference
- 스코프: 식별자에 대한
유효 범위
- 스코프 체인: 식별자의 유효범위를
안에서 바깥으로
차례로 검색하는 것
- LexicalEnvironment의
outerEnvironmentReference
를 통해 스코프 체인
스코프 체인
- outerEnvironmentReference는
현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조
- outerEnvironmentReference는 연결 리스트의 형태: 선언 시점의 LexicalEnvironment -> 마지막에는 전역 컨텍스트의 LexicalEnvironment
- 여러 스코프에서 동일한 식별자를 선언한 경우, 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능
이제 다시 앞선 코드를 살펴보자
var a = 1;
function outer() {
function inner() {
console.log(a);
var a = 3;
}
inner();
console.log(a);
}
outer();
console.log(a);
전역 스코프에 a
가 1
로 존재하지만, inner 스코프는 현재 컨텍스트의 LexicalEnvironment부터 검색하기 때문에 undefined
인 a를 반환한다.
변수은닉화, 함수 내부에서 변수를 선언했기 때문에 전역 공간에서 선언한 동일한 이름의 변수에 접근할 수 없음
전역변수와 지역변수
- 전역변수: 전역 공간에서 선언한 변수
- 지역변수: 함수 내부에서 선언한 변수
this
- 실행 컨텍스트의 thisBinding에는 this로 지정된 객체가 저장
- 실행 컨텍스트 활성화 당시에 this가 지정되지 않은 경우, this에는 전역 객체 저장
정리
- 실행 컨텍스트: 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
- VariableEnvironment: 초기 상태 유지
- LexicalEnvironment: 함수 실행 도중에 변경되는 사항 즉시 반영
- environmentRecord: 매개변수명, 변수의 식별자, 선언한 함수의 함수명 등 수집
- outerEnvironmentReference: 바로 직전 컨텍스트의 LexicalEnvironment 정보 참조
- 호이스팅: environmentRecord의 수집 과정
- 스코프: 변수의 유효범위
- 스코프 체인: 안에서 밖으로 변수 찾기
- 전역변수와 지역변수
참고자료
코어 자바스크립트