실행 컨텍스트

heejung·2022년 1월 8일
0

코어자바스크립트

목록 보기
2/4

실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.
동일한 환경에 있는 코드를 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고 콜 스택에 쌓은 후, 가장 위에 쌓인 컨텍스트와 관련된 코드를 실행한다. 그리고 해당 컨텍스트가 종료되면 콜 스택에서 제거된다.

자바스크립트는 어떤 실행 컨텍스트가 활성화되는 시점에
1. 선언된 변수를 끌어올리고 (호이스팅)
2. 외부 환경 정보를 구성하고
3. this 값을 설정한다.

실행 컨텍스트 객체에 저장되는 정보는 다음과 같다.

  • VariableEnvironment
  • LexicalEnvironment
  • ThisBinding

VariableEnvironment

실행 컨텍스트를 생성할 때 VariableEnvironment에 정보를 먼저 담고, 이를 복사해서 LexicalEnvironment를 만든다.
내용은 LexicalEnvironment와 같지만 최초 실행 시의 스냅샷을 유지한다는 차이가 있으며, LexicalEnvironment를 만든 후에는 LexicalEnvironment를 주로 활용하게 된다.

LexicalEnvironment

컨텍스트를 구성하는 환경 정보들을 사전에서 접하는 느낌으로 모아놓은 것이다.
LexicalEnvironment의 내부 구성요소에는 environmentRecord와 EnvironmentRefference가 있다.

environmentRecord

현재 컨텍스트와 관련된 코드의 식별자 정보들이 순서대로 저장된다. (변수명, 함수 선언, 매개변수 이름 등)
이렇게 정보 수집을 통해 자바스크립트 엔진은 코드 실행 전에 이미 코드의 변수명들을 다 알고있는 상태가 된다. 그래서 실제 코드를 실행할 때, 식별자 선언 이전에 식별자를 호출해도 에러가 나지 않고 정상적으로 호출이 된다.
여기서 호이스팅이라는 개념이 등장한다.

호이스팅은 '끌어올리다'의 의미인 'hoist'와 '-ing'를 붙여 만든 동명사로, 식별자들을 최상단으로 끌어올려놓은 후 실제 코드를 실행하는 것처럼 보이는 현상을 말한다.
자바스크립트 엔진이 식별자들을 실제로 끌어올리는 건 아니지만 편의상 그렇게 간주하자는 것이다.
environmentRecord에는 식별자만 저장이 되기 때문에 할당값은 실제로 값을 할당하는 코드에 도달해야만 알 수 있다.
즉, 선언문 이전에 식별자를 호출하면 에러는 나지 않지만 값이 할당되지 않아 undefined를 반환하게 된다.

호이스팅과 함께 함수 선언문, 함수 표현식의 개념도 알아두는 게 좋다.

  • 함수 선언문
    function 정의부만 존재
function sum(a, b) {
  return a + b;
}
  • 함수 표현식
    정의한 function을 별도의 변수에 할당
var multiply = function (a, b) { 
  return a * b;
}

위에서 environmentRecord에 저장되는 식별자는 변수명, 함수 선언 등이 있다고 했다. 변수는 변수명만 저장되지만 함수는 함수 자체를 저장하는 것이다.
따라서, 함수 선언문은 함수 자체가 저장되고 함수 표현식은 함수를 변수에 할당했으니 변수로 취급되어 변수명만 저장된다.

두 함수를 선언 이전에 호출하면 어떻게 되는지 보자.

sum(1, 2); // 3
multiply(1, 2); // multiply is not a function

function sum(a, b) {
  return a + b;
}

var multiply = function (a, b) { 
  return a * b;
}

함수 선언문은 environmentRecord가 함수 자체를 알고 있으니 문제없이 실행이 된다.
하지만 함수 표현식은 environmentRecord가 multiply라는 식별자만 알고 있을 뿐 함수인지조차 모르는데 함수로 실행하려고 하니 당연하게도 실행이 안 된다. 그래서 함수 표현식을 사용할 때는 무조건 선언 이후에 호출해야 한다.

간단하거나 짧은 코드를 짤 때는 상관없지만, 복잡한 코드를 짜거나 협업을 해야할 때는 함수 선언문보다 함수 표현식을 사용하는 게 더 안전하다. 아무데서나 불러다 쓸 수 있는 전역변수같은 느낌의 함수 선언문은 의도치않은 값의 변경 등과 같은 문제를 발생시킬 위험이 있기 때문이다.

outer-EnvironmentRefference

현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조한다.
즉, 상위 함수의 LexicalEnvironment를 참조하는 것이다.

var outer = function () {
  var inner = function () { 
    ...
  }
}

이렇게 되면 inner는 outer의 LexicalEnvironment를 참조하고, outer는 전역 컨텍스트의 LexicalEnvironment를 참조하여 식별자의 유효범위를 안에서부터 바깥으로 검색해나가게 되는데, 이것을 스코프 체인이라고 한다.
가장 가까운 요소부터 접근할 수 있으므로 만약 여러 스코프에서 동일한 식별자를 선언했다면, 현재 스코프 체인상에서 가장 가까운 식별자에게만 접근할 수 있다.

profile
프론트엔드 공부 기록

0개의 댓글