JavaScript

[자바스크립트] 실행컨텍스트의 생성과 식별자 검색과정

문승주 2023. 7. 14. 23:18
반응형

 내용은 이웅모 님의 모던 "자바스크립트 DeepDive" 책을 보고 정리한 내용입니다. 저작권 보호를 위해 책의 내용은 요약되었습니다.

 

예시)

var a = "a";
const b = "b";

function first(d){
  var a = "A";
  const b = "B";

  function second(e){
    const c = "C";
    console.log(a + b + c + d + e)
  }
  second("E");
}
first("D"); // ABCDE

 

1. 전역 객체 생성

전역 객체는 전역 코드 평가 이전에 생성된다. 브라우저에서는 'window' 객체를 의미하며 전역객체도 Object.prototype을 상속받기에 프로토타입 체인의 일원이다.

 

2. 전역 코드 평가

소스코드 로드시 자바스크립트 엔진은 전역 코드를 평가한다.

 

2-1. 전역 실행 컨텍스트 생성

비어있는 전역 실행 컨텍스트를 생성하여 실행 컨텍스트 스택에 푸시한다.

 

2-2. 전역 렉시컬 환경 생성

전역 렉시컬 환경을 생성하고 전역 실행 컨텍스트에 바인딩한다.

전역 변수 x와 전역 함수 example은 객체 환경 레코드를 통해 전역 객체의 프로퍼티와 메서드가 된다.

 

2-2-1. 전역 환경 레코드 생성

전역 환경 레코드는 전역 변수를 관리하는 전역 스코프, 전역 객체의 빌트인 전역 프로퍼티와 빌트인 전역 함수, 표준 빌트인 객체를 제공한다.

 

- 전역 환경 레코드의 종류

객체 환경 레코드

  • 전역 코드 과정에서 var 키워드로 선언한 전역 변수와 함수 선언문으로 정의한 전역 함수는 BindingObject를 통해 전역 객체의 프로퍼티와 메서드가 된다.
  • var 키워드로 선언된 전역 변수와 함수 선언문으로 정의된 전역 함수는 식별자 없이 참조할 수 있다.
  • var 키워드로 선언한 변수는 전역 코드 평가 시점에 변수 식별자 키를 등록하기에 변수 선언문 이전에도 참조할 수 있다.
  • 함수 선언문으로 정의한 함수가 평가되면 함수 이름과 동일한 이름의 식별자를 전역 객체의 키로 등록하기에 함수 선언문 이전에 호출할 수 있다.

선언적 환경 레코드

  • let, const 키워드로 선언한 전역 변수는 선언전 환경 레크드에 등록되고 관리된다.
  • let과 const 선언된 변수는 선언 단계와 초기화 단계로 나뉘어진다.
  • 선언 단계: 변수가 해당 스코프에 등록되며, 스코프에서 접근 가능해진다.
  • 초기화 단계: 변수에 실제로 값을 할당하고 초기화하는 단계이다.
  • 일시적 사각지대 (TDZ) : 변수가 선언된 위치에서부터 초기화되기 전까지의 구간을 일시적 사각지대라고 하고 해당 변수에 접근하려고 하면 ReferenceError가 발생한다.

 

예시)

let a = 10;
{
  console.log(a); // ReferenceError: Cannot access 'a' before initialization
  let a = 20; // 변수 a가 선언되었지만 아직 초기화되지 않음
}

 

2-2-2. this 바인딩

전역 환경 레코드는 [[GlobalThisValue]] 내부 슬롯에 this가 바인딩된다. 객체 환경 레코드와 선언적 환경 레코드에는 this 바인딩이 없다.

 

2-2-3. 외부 렉시컬 환경에 대한 참조 결정

현재 소스코드의 상위 스코프를 가리킨다. 이를 통해 단방향 링크드 리스트인 스코프 체인을 구현한다.

 

3. 전역 코드 실행

전역 코드가 순차적으로 실행되는데 변수 할당문이 실행되면 전역변수 a, b에 값이 할당한다.변수 할당문 또는 함수 호출문 실행시 변수 또는 함수 이름이 선언된 식별자인지 확인하는데 동일한 이름의 식별자가 다른 스코프에 여러개 존재할 수 있기에 실행 중인 실행 컨텍스트에서 식별자를 검색하여 식별자를 결정하고 이를 식별자 결정이라고 한다.

 

 

4. first 함수 코드 평가

first 함수가 호출되면 전역 코드의 실행을 일시 중단하고 first 함수 내부로 코드의 제어권이 이동한다.

 

4-1. 함수 실행 컨텍스트 생성

first 함수 실행 컨텍스트를 생성하고 함수 렉시컬 환경이 완성된 다음 실행 컨텍스트 스택에 푸시된다.

 

4-2. 함수 렉시컬 환경 생성

first 함수 렉시컬 환경을 생성하고 first 함수 실행 컨택스트에 바인딩한다.

 

4-2-1. 함수 환경 레코드 생성

함수 환경 레코드는 매개변수, arguments 객체, 함수 내부에서 선언한 지역 변수와 중첩 함수를 등록하고 관리한다.

 

4-2-2. this 바인딩

함수 환경 레코드의 [[ThisValue]] 내부 슬롯에 this가 바인딩된다. first 함수는 일반 함수로 호출되므로 this는 전역 객체를 가리킨다.

 

4-2-3. 외부 렉시컬 환경에 대한 참조 결정

first 함수 정의가 평가된 시점에 실행 중인 실행 컨텍스트의 렉시컬 환경의 참조가 할당된다. first 함수는 전역 코드에 정의되어 있기에 실행 컨텍스트도 전역 실행 컨텍스트이고 외부 렉시컬 환경에 대한 차보에도 전역 렉시컬 환경의 참조가 할당된다.

 

 

5. first 함수 코드 실행

런타임시 first 함수의 코드가 실행되는데 매개변수에 인수가 할당되고, 지역 변수 a. b에 값이 할당된다. 이후에는 함수 second가 호출된다. 실행 컨텍스트의 렉시컬 환경에서 식별자를 검색하는데 first 함수 렉시컬 환경에서 식별자 a.b를 검색하소 식별자가 없으면 외부 렉시컬 환경에 대한 참조가 가리키는 헥시컬 환경에서 식별자를 검색한다.

 

 

6. second 함수 코드 평가

second 함수 코드를 평가하는데 과정은 first 함수 코드 평가와 동일하다.

 

 

7. second 함수 코드 실행

first 함수 코드 실행과 동일하고 지역변수 c에 값이 할당된다. 이후에 console.log(a + b + c + d + e) 를 실행하는데 a,b,c,d,e에 대한 식별자를 검색한다. a. d. e는 first 함수 렉시컬 환경, b와 c는 second 함수 렉시컬 환경에서 검색된다.

 

 

8. second / first 함수 코드 실행 종료

second, first 함수 순으로 함수 코드의 실행이 종료된다. 이때 실행 컨텍스트 스택에서 해당 함수 실행 컨텍스트가 pop 되며 제거되는데 렉시컬 환경은 제거되지 않고 남아있기에 누군가 참조하고 있다면 해당 함수 렉시컬 환경은 가비지 컬렉션에 의해 소멸하지 않는다.

 

※ 객체가 누군가에게 참조되지 않게되면 가비지 컬렉터에 의해 소멸하게 된다.

 

 

9. 전역 코드 실행 종료

더 이상 실행할 전역 코드가 없으면 전역 실행 컨텍스트도 pop되머 제거된다.

 

 

 

 

 

 

반응형