Execution Context (실행 컨텍스트)

: 코드를 실행하는데 필요한 환경을 제공하는 객체, 식별자 결정을 더욱 효율적으로 하기 위한 수단

환경(Environment) - 코드 실행에 영향을 주는 조건이나 상태

var num = 0;

function one() {
	console.log(num);
    
    function two() {
    	console.log(num + 1);
    }
    one();
}
two();

- 위와 같은 코드를 구성하면 아래의 그림과 같은 실행 컨텍스트 과정을 거치게 된다. 

실행 컨텍스트 과정

1. LIFO(Last In First Out)의 구조를 가진 실행 컨텍스트 스택(Stack)이 생성된다.

2. 전역 실행 컨텍스트가 생성되고 실행 컨텍스트 스택에 쌓여 애플리케이션이 종료될 때까지 유지된다.

3. 함수를 호출하면 해당 함수의 실행 컨텍스트가 생성되어 직전에 실행된 실행 컨텍스트 위에 쌓이게 된다.

4. 함수 실행을 끝마치면, 해당 실행 컨텍스트를 파기하고 직전의 실행 컨텍스트에 컨트롤을 반환하게 된다.

 

출처 : 모던 자바스크립트 Deep Dive


Hoisting 

: 선언문이 마치 최상단에 끌어올려진 듯한 현상

생성 단계와 실행단계로 나누어진다.

 

생성 단계(Creation Phase) - Execution Context 생성

: 선언문만 실행해서 Environment Record에 기록

 

실행단계(Execution Phase) - 선언문 외 나머지 코드 순차적 실행

: Environment Record를 참조하거나 업데이트

 

변수 호이스팅

- var : 호이스팅시 암묵적으로 undefined로 초기화를 시켜준다 (선언과 초기화가 동시에 이루어짐)

console.log(num); //undefined

var num = 1;

- 위의 코드를 실행 시 js에선 undefined를 출력하게 되어있다.

그 이유는 var는 호이스팅 시 암묵적으로 undefined로 초기화를 하게 되는데 선언 부보다 위에서 실행 시에 미리 초기화시켜둔 undefined가 출력되게 되는 것이다. 

 

- const, let : 호이스팅시 Temporal Dead Zone(일시적 사각지대)가 존재하며, 선언 이전에 식별자를 참조하게 된다면 참조할 수 없기에 Reference Error가 발생한다.

console.log(num); // ReferenceError

const num = 1;
console.log(num); // ReferenceError

let num = 1;

- 위 두 코드는 실행 시 동일하게 ReferenceError를 뱉어낸다. 

그 이유는 let과 const는 호이스팅시 undefined로 초기화 되는것이 아니기때문에 TDZ가 존재하여, 선언 이전에 참조하면 참조할수없어서 에러를 만나게되는 것이다.

 

함수 호이스팅

 

- 함수 표현식(Function Expression)

: 변수에 함수를 담아서 사용하기 때문에, 변수 호이스팅과 동일하게 동작한다. (선언문 전에 함수를 호출할 수 없다.)

 

study(); // Type Error ( undefined )

var study = () => {
	// do
};

study(); // Reference Error

const study = () => {
	// do
};

 

- 함수 선언문(Function Declaration)

: 변수가 아닌 함수로 선언했기 때문에 선언과 동시에 함수가 생성되어 선언 전에도 함수를 호출할 수 있다.

study(); // Ok

function study() {
	// do
}

Outer Environment Reference (외부 환경 참조)

: 바깥 Lexical Environment(정적 환경)를 가리킴

function outer() {
    var num = 10;
    function inner(){
        console.log(num);
    }
    inner();
}
outer();

- 위 코드 실행 시 10이라는 값이 출력이 된다.

- num이라는 변수는 inner라는 함수의 scope에 존재하지 않지만, outer함수에 존재하는 num이라는 변수를 찾아서 값을 출력해준 것이다. 이처럼 javascript는 식별자 결정 시에 현재 scope에 해당 식별자가 없다면, 실행컨텍스트에 존재하는 바깥(outer) 환경에서 식별자를 찾고 Global Context까지 도달했지만 없을 경우 Reference Error를 뱉게 된다.

 

- 식별자 결정(Identifier Resolution)

: 코드에서 변수나 함수의 값을 결정하는 것

 

- 변수 섀도잉(Variable Shadowing)

: 동일한 식별자로 인해 상위 스코프에서 선언된 식별자의 값이 가려지는 현상

 

var num = 20;
function outer() {
    var num = 10;
    function inner(){
        console.log(num);
    }
    inner();
}
outer();

- 위 코드를 실행 시 10이라는 값이 출력된다.

 - 전역에 num이라는 변수가 20으로 선언되었지만, inner 함수 실행 시에 outer에 num이라는 변수가 먼저 선언되어있어 상위 식별자인 전역으로 선언된 num이 가려지는 현상이 발생한다. 이 현상을 변수 섀도잉이라고 한다. 만약 outer에 num이라는 식별자가 존재하지 않는다면, 더 상위 식별자를 찾게 되어 inner에서는 20이라는 값을 출력하게 된다.

 

 

- 스코프 체인(Scope Chain)

: 식별자를 결정할 때 활용하는 스코프들의 연결 리스트 

[ 스코프 체이닝 : 식별자를 결정하기 위해 찾는 과정 ]

 

출처 : YOUTUBE 우아한 Tech [10분 테코톡] 하루의 실행 컨텍스트