[240331] 22장 실행 컨텍스트 (2)
22장 실행 컨텍스트 (2)
- 전역 코드 평가
- 전역코드 평가는 다음과 같은 순서로 진행
- 전역 실행 컨텍스트 생성
-
전역 렉시컬 환경 생성
2.1. 전역 환경 레코드 생성
2.1.1 객체 환경 레코드 생성
2.1.2 선언적 환경 레코드 생성
2.2 this 바인딩
2.3 외부 렉시컬 환경에 대한 참조 결정
2.1.1 객체 환경 레코드는 var 변수, 함수 선언문으로 정의한 전역 함수,빌트인 전역 프로퍼티와 빌트인 전역 함수 등을 관리
- BindingObject 는 전역 객체 생성에서 생성된 객체다.
- 전역 코드 평가 과정에서 var 키워드로 선언한 전역 변수와 함수 선언문으로 정의된 전역 함수는 전역 환경 레코드의 객체 환경 레코드에 연결된 BindingObject를 통해 전역 객체의 프로퍼티와 메서드가 된다.
- 선언단계, 초기화 단계 같이 진행함
- 전역 코드 평가 시점에 객체 환경 레코드에 바인딩된 BindingObject 를 통해 전역 객체에 변수 식별자를 키로 등록한 다음 암묵적으로 undefined 를 바인딩한다.
- 함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출할 수있다.
2.2.2 let const 키워드로 선언한 전역 변수는 선언적 환경 레코드 관리
- 개념적 블록 내에 존재하게 된다고 했었는데, 전역 환경 레코드의 선언적 환경 레코드를 말함
- window.y 와 같이 전역 객체의 프로퍼티에 참조할 수 없음
- 선언단계, 초기화 단계가 분리되어 진행되기 때문에 변수 선언문에 도달하기 전까지 일시적 사각지대에 빠지게 된다.
- 실제로
라는 값이 바인딩 (변수에 접근할 수 없도록 하는 표현)
2.2 this 바인딩
- 전역 환경 레코드의 [[GlobalThisValue]] 내부 슬롯에 this 가 바인딩
- this 바인딩은 전역 환경 레코드와 함수 환경 레코드에만 존재
- 전역 환경 레코드를 구성하는 객체 환경 레코드와 선언적 환경 레코드에는 this 바인딩 없다.
2.3 외부 렉시컬 환경에 대한 참조 결정
- 상위 스코프를 가리킴
- 단방향 링크드 리스트인 스코프 체인을 구현
- 전역 렉시컬 환경의 외부 렉스컬 환경에 대한 참조는 null
- 종점을 의미함
- 전역코드 평가는 다음과 같은 순서로 진행
- 전역코드 실행
- 식별자 결정을 위해 식별자를 검색할 때는 실행 중인 실행 컨텍스트에서 식별자를 검색하기 시작함
- 실행 중인 실행 컨텍스트의 렉시컬 환경에서 식별자 검색할 수 없으면 외부 렉시컬 환경에 대한 참조가 가리키는 렉시컬 환경 (상위 스코프)로 이동하여 검색 → 스코프 체인 동작 원리
- 이처럼 실행 컨텍스트는 소스코드를 실행하기 위해 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역
- foo 함수 코드 평가
const x = 1;
function foo() {
const y = 2;
function bar() {
const z = 3;
console.log(x + y + z);
}
bar();
}
foo(); // <- 호출 직전
- 전역 코드 평가를 통해 전역 실행 컨텍스트가 생성되었고 실행하고 있음
- foo 함수가 호출되면 전역 코드의 실행을 중단하고 foo 함수 내부로 코드의 제어권 이동 , 함수 코드를 평가하기 시작
- 함수 실행 컨텍스트 생성
-
함수 렉시컬 환경 생성
2.1 함수 환경 레코드 생성
2.2 this 바인딩
2.3 외부 렉시컬 환경에 대한 참조 결정
- 함수 실행 컨텍스트 생성
- 함수 렉시컬 환경이 완성된 다음 실행 컨텍스트 스택에 푸시
- 함수 렉시컬 환경 생성
- foo 함수 실행 컨텍스트에 바인딩
- 마찬가지로 2개의 컴포넌트 (환경 레코드, 외부 렉시컬 환경)에 대한 참조로 구성
2.1 함수 환경 레코드 생성
- 매개변수, argument 객체, 함수 내부에서 선언한 지역 변수와 중첩 함수를 등록하고 관리
2.2 this 바인딩
- [[ThisValue]] 내부 슬롯에 바인딩
- 일반 함수로 호출되면 전역 객체가 들어있음
2.3 외부 렉시컬에 대한 참조
- foo 함수가 정의가 평가된 시점에 실행 중인 실행 컨텍스트의 렉시컬 환경의 참조가 할당
- [[Enviroment]] 에 함수의 상위 객체를 저장함
- 함수 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 할당되는 것은 함수 객체의 내부 슬롯 [[Enviroment]]에 저장된 렉시컬 환경의 참조다.
- 함수 객체의 내부 슬롯 [[Enviroment]] 가 렉시컬 스코프를 구현하는 매커니즘
- foo 함수 코드 실행
- bar 함수 코드 평가
- bar 함수 코드 실행
- console 식별자 검색
- 상위 스코프로 쭉 가다가 전역 렉시컬 환경의 객체 환경 레코드의 BindingObject 를 통해 찾을 수 있다.
- bar 함수 코드 실행 종료
- 실행 컨텍스트가 소멸 되었다 하더라도 bar 함수 렉시컬 환경을 누군가 참조하고 있다면 소멸하지 않는다.
- foo 함수 코드 실행 종료
- 전역 코드 실행 종료
실행 컨텍스트와 블록 레벨 스코프
let x = 1;
if(true) {
let x = 10;
console.log(x); // 10
}
console.log(x); // 1
- var 함수 레벨 스코프
- let const 블록 레벨 스코프
- if 문의 코드 내에서 let 변수가 선언되었다. 따라서 if 문의 블록이 실행되면 if 문의 코드 블록을 위한 블록 레벨 스코프를 생성해야함
- 이를 위해 선언적 환경 레코드를 갖는 렉시컬 환경을 새롭게 생성하여 기존의 전역 레시컬 환경을 교체한다.
- 이때 새롭게 생성된 if 문의 코드 블록을 위한 렉시컬 환경의 외부 렉시컬 환경에 대한 참조는 if 문이 실행되기 이전의 렉시컬 환경을 가리킴
- if 문이 종료되면 if 문의 코드 블록이 실행되기 이전으로 되돌린다.
- if 문뿐 아니라 블록 레벨 스코프를 생성하는 모든 블록문에 적용
Leave a comment