실행 컨텍스트란?
- 자바스크립트가 실행되는 환경으로 함수를 실행할 때 필요한 조건, 환경정보를 제공하는 객체입니다.
실행 컨텍스트를 이해하면 Scope, hoisting, closure, this와 같은 중요한 동작을 이해할 수 있습니다.
실행 컨텍스트의 내부
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var a = 1;
function outer() {
console.log(a); // 실행 순서(1): 1출력
function inner() {
// var a; --> undefined (호이스팅)
console.log(a); // 실행 순서(2): 1출력
var a = 3;
}
inner();
console.log(a); // 실행 순서(3): 1출력
}
outer();
console.log(a); // 실행 순서(4): 1출력
아래는 위 코드를 실행 컨텍스트 내부로 추상화한 것입니다.
Variable Environment와 Lexical Environment는 모두 식별자 정보를 수집합니다.
차이점은 Varable Environment는 변수들 값의 변화가 생기면 실시간으로 반영되지 않고
Lexical Environment는 식별자의 바인딩된 값을 기록하고 추적합니다
실행 컨텍스트의 구성 중 Lexcal Environment에 살펴보면 아래와 같습니다.
Lexical Environment
Environment Record (환경 레코드)
실행 컨텍스트를 구성하는 환경 정보들을 모아 사전처럼 구성한 객체로 변수의 값들이 변화가 생기면 실시간으로 반영됩니다.
생성 단계
- 선언문만 실행해서 환경 레코드에 기록합니다.
- 실행 컨텍스트가 생성되는 순간 가장 먼저 하는 일입니다.
실행 단계
- 선언문 외 나머지 코드를 순차적으로 실행하여 환경 레코드에 기록된 식별자를 참조하거나 업데이트합니다.
전체 코드를 스캔하면서 선언할 게 있다면 먼저 선언해 두는 과정에서 실행 콘텍스트 안에 있는 환경 레코드에 기록해둡니다.
이렇게 스캔하고 준비하는 단계를 생성 단계라고 하고 코드를 순차적으로 실행하면서
환경 레코드에 기록된 정보를 참조하거나 업데이트하는 과정을 실행단계라고 합니다.
Hoisting(호이스팅) 이해하기
- 선언문이 최상단으로 끌어올려진 듯한 현상입니다.(함수 표현식 동일하게 동작)
- let 또는 const로 선언했을 때, 선언 이전에 식별자를 참조할 수 없습니다. (Reference Error 일시적 사각지대)
- 아래 소스에서 함수 b와 같이 함수 선언문 방식으로 함수를 선언하는 경우에는 선언과 동시에 함수가 생성되어 끌어올려지기 때문에 선언 전에도 함수를 사용할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// var a; --> undefined
console.log(a); // undefined
/*
function b() {
console.log("b 함수 호출");
}
*/
console.log(b()); // b 함수 호출
// var c; --> undefined
console.log(c()); // Reference Error(undefined를 함수 처럼 호출한 것)
var a = 3; // a = 3;
console.log(a); // 3
function b() {
console.log("b 함수 호출");
}
var c = function () {
console.log("c 함수 호출");
};
/*
c = function () {
console.log("c 함수 호출");
};
*/
Outer Environment (Scope Chain)
- 외부 환경을 참조합니다.
- 바깥 Lexical Environment를 가리킵니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var a = 1;
function outer() {
console.log(a); // 실행 순서(1): 1출력
function inner() {
// var a; --> undefined (호이스팅)
console.log(a); // 실행 순서(2): 1출력
var a = 3;
}
inner();
console.log(a); // 실행 순서(3): 1출력
}
outer();
console.log(a); // 실행 순서(4): 1출력
위 소스에서 console.log(a)
출력 과정을 콜스택과 함께 실행 컨텍스트를 설명하면 아래와 같습니다.
- 전역 컨텍스트가 생성되고 전역 공간을 한 줄 한 줄 실행합니다.
- 변수
a
와 함수ourter
를 선언하여 환경 레코드에 식별자를 바인딩합니다. (생성 단계) - 함수
outer()
를 호출하면outer
함수의 실행 콘텍스트가 생성되어 콜스택에 쌓입니다.
outer
함수에inner
함수를 선언하여 환경 레코드에 식별자를 바인딩합니다. (생성 단계)outer
함수에 첫 줄에console.log(a)
가 실행되고 console.log 컨텍스트가 생성되어 콜스택에 쌓입니다.
a
를 찾아 찾아 올라가게(scope chain) 되고 1을 출력하고console.log(a)
컨텍스트는 사라지고 콜스택에서 빠져나옵니다.
inner
함수가 호출되면inner
함수의 콘텍스트가 생성됩니다.
inner
함수의 변수a
를 선언하여 식별자를 바인딩합니다. (생성 단계)inner
함수 내의console.log(a)
를 실행하면console.log
실행 컨텍스트가 생성되어 콜스택에 쌓입니다.
a
는 hoisting 되어 undefined를 출력하고console.log
실행 컨텍스트가 사라지고 콜스택에서 빠져나옵니다.
inner
실행 컨텍스트가 사라지고 콜스택을 빠져나옵니다.
outer
함수의 마지막 줄인console.log(a)
가 실행되면 실행 컨텍스트가 생성되고 콜스택에 쌓입니다.
a
를 찾아 찾아 올라가(scope chain) 1을 출력한 후console.log
실행 컨텍스트가 사라지고 콜스택을 빠져나옵니다.
outer
실행 컨텍스트가 사라지고 콜스택을 빠져나옵니다.
- 전역 컨텍스트의 마지막 줄인
console.log(a)
가 실행되고console.log
실행 컨텍스트가 생성되어 콜스택에 쌓입니다.
console.log(a)
의 1을 출력하면console.log
실행 컨텍스트가 사라지고 콜스택을 빠져나옵니다.
- 컨텍스트도 종료가 됩니다.