[자바스크립트] 실행 컨텍스트란 ? (1)

minidoo·2020년 10월 22일
0
post-thumbnail

'실행 컨텍스트' 란?

실행 컨텍스트란 실행할 코드에 제공할 환경 정보들을 모아놓은 객체

  • 선언된 변수를 위로 끌어올린다. (호이스팅)
  • 외부 환경 정보를 구성한다.
  • this 값을 설정한다.

스택(Stack)과 큐(Queue)

스택(Stack)은 출입구가 하나인 LIFO(Last In First Out) 구조이다.
스택에 a, b, c, d를 순서대로 저장하면 꺼낼 때 d, c, b, a 순서대로 나온다.

큐(Queue)는 양쪽이 모두 열려있는 FIFO(First In First Out) 구조이다.
큐에 a, b, c, d 를 순서대로 저장하면 꺼낼 때 a, b, c, d 순서대로 나온다.

실행 컨텍스트의 콜 스택 (Call Stack)

동일한 환경에 있는 코드를 실행할 때 필요한 환경 정보들들 모아 컨텍스트를 구성한다. 이를 콜 스택에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련있는 코드들을 실행한다.

실행 컨텍스트를 구성할 수 있는 방법은 전역, eval() 함수, 함수 실행이 있다.

// ------------------------------- (1)
var a = 1;
function outer() {
    function inner() {
   	console.log(a); // undefined ----- (a)
        var a = 3;	
    }
    inner(); // ------------------ (2)
    console.log(a);	// 1 ----- (b)
}
outer(); // ---------------------- (3)
console.log(a);		// 1 ----- (c)

  1. 전역 컨텍스트는 자바스크립트 파일이 열리는 순간 활성화된다. (1)이 콜 스택에 담긴다.
  2. (3)에서 outer 함수를 호출하면 outer 실행 컨텍스트를 생성하고 콜 스택에 담는다.
  3. outer 함수를 실행한다.
  4. (2)에서 inner 함수를 호출하면 inner 실행 컨텍스트를 생성하고 콜 스택에 담는다.
  5. inner 함수를 실행한다. 아직 a 값을 할당받지 못했기 때문에 (a)undefined가 찍힌다. a에 3을 할당하고 inner 함수의 실행이 종료되면서 inner 실행 컨텍스트가 콜 스택에서 제거된다.
  6. (b)a 값을 출력하고 outer 함수의 실행이 종료되면 outer 실행 컨텍스트가 콜 스택에서 제거된다.
  7. 마지막 줄의 (c)a를 출력하고 전역 컨텍스트가 콜 스택에서 제거되면 종료된다.

즉, 어떤 실행 컨텍스트가 콜 스택의 맨 위에 쌓이는 순간이 곧 현재 실행할 코드에 관여하게 되는 시점이다.

실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체라고 했다.
여기에 담기는 정보에는 VariableEnvironment, LexicalEnvironment, ThisBinding이 있다.


실행 컨텍스트의 환경 정보

VariableEnvironment

VariableEnvironment는 현재 컨텍스트 내의 식별자들에 대한 정보와 외부 환경 변수를 말한다.
최초 실행 시의 스냅샷을 유지하며, 변경 사항은 반영되지 않는다.

LexicalEnvironment

LexicalEnvironment는 변경 사항이 실시간으로 반영된다.
LexicalEnvironment 내부는 environmentRecordouter-EnvironmentReference로 구성되어 있다.

environmentRecord

environmentRecord 에는 현재 컨텍스트와 관련된 코드들의 식별자 정보들이 저장된다.

  • 함수에 지정된 매개변수 식별자
  • 선언한 함수가 있을 경우 그 함수 자체
  • var로 선언된 변수의 식별자

변수 정보를 수집하는 과정을 모두 마쳐도 아직 실행 컨텍스트가 관여할 코드들은 실행되기 전의 상태이다.
즉, 자바스크립트는 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다.

여기서 끌어리는 것을 호이스팅(hoisting)이라고 한다.

호이스팅 (hoisting)

예제 1 )

function a(x) {
    console.log(x);
    var x;
    console.log(x);
    var x = 2;
    console.log(x);
}
a(1)

위의 코드에서 우르는 순서대로 1, undefined, 2 가 출력될 것이라고 생각한다.
하지만 실제로 그렇지 않다. 호이스팅을 거치기 때문이다.

식별자에는 매개변수 이름, 함수 선언, 변수명 등이 있음을 기억하면서 식별자를 하나씩 호이스팅 해보자.

// 1. 매개변수를 호이스팅한다.
function a() {
    var x = 1;
    console.log(x);
    var x;
    console.log(x);
    var x = 2;
    console.log(x);
}
a()

// 2. 변수명을 호이스팅한다. ('선언부'만 호이스팅 )
function a() {
    var x;
    var x = 1;
    console.log(x); 		
    console.log(x);	    
    var x = 2;
    console.log(x);          
}
a()

<output>
1
1
2

예제 2)

function a() {
    console.log(b);
    var b = 'bbb';
    console.log(b);
    function b() {}
    console.log(b);
}
a()

<예상 output>
에러 또는 undefined
'bbb'
function b() {}
// 1. 변수명과 함수를 호이스팅한다.
// 변수명은 선언부만 함수는 전체를 호이스팅한다. 
function a() {
    var b;
    function b() {}
    console.log(b);
    b = 'bbb';
    console.log(b);
    console.log(b);
}
a()

// 2. 함수 선언문은 함수명으로 선언한 변수에 함수를 할당한 것으로 여긴다.
function a() {
    var b;
    var b = function b() {}
    console.log(b);
    b = 'bbb';
    console.log(b);
    console.log(b);
}
a()

<output>
function b() {}
'bbb'
'bbb'

참고 서적

코어 자바스크립트(Core JavaScript)
https://book.naver.com/bookdb/book_detail.nhn?bid=15433261

0개의 댓글