fffo
실행 컨텍스트 본문
실행 컨텍스트(execution context)
- 실행 컨텍스트란?
- 스코프와 코드 실행순서 관리를 구현한 내부 메커니즘
- 스코프는 식별자를 등록하고 관리하는 역할을 가짐
- 실행 컨텍스트의 렉시컬 환경(lexical environment)으로 스코프를 관리
- 실행 컨텍스트 스택으로 코드 실행 순서를 관리
- 소스코드를 실행하는 데 필요한 환경을 제공하고 실행 결과를 실제로 관리하는 영역
- 스코프와 코드 실행순서 관리를 구현한 내부 메커니즘
소스코드의 타입
- ECMAScript 사양은 소스코드를 4가지 타입으로 구분하고, 각 타입의 소스코드가 평가될 때 각각의 실행 컨텍스트를 생성한다
- 전역코드(global code) : 전역에 존재하는 소스코드. 전역에 정의된 함수, 클래스 등 내부 코드는 제외
- 함수 코드 : 함수 내부에 존재하는 소스코드. 함수 내부에 중첩된 함수, 클래스 등의 내부 코드는 제외
- eval 코드 : 빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드
- 모듈 코드 : 모듈 내부에 존재하는 소스코드. 모듈 내부의 함수, 클래스 등의 내부 코드는 포함하지 않음
- 각 타입마다 실행 컨텍스트를 생성하는 과정과 관리 내용이 다름
실행 컨텍스트 스택
- 실행 컨텍스트 스택 : 코드의 실행 순서를 관리하는 스택 형태의 자료구조
- 실행 컨텍스트 스택의 최상위는 항상 실행 중인 코드의 실행 컨텍스트(running execution context)임
렉시컬 환경(lexical evironment)
- 렉시컬 환경 : 식별자와 식별자에 바인딩된 값, 상위 스코프에 대한 참조를 기록하는 자료구조
- 실행 컨텍스트는 LexicalEnvironment 컴포넌트와 VariableEnvironment 컴포넌트로 구성됨
- 생성 초기에 두 컴포넌트는 하나의 동일한 렉시컬 환경을 참조함
- 몇 가지 상황에 따라 VariableEnvironment 컴포넌트를 위한 새로운 렉시컬 환경을 생성할 수도 있음
- 렉시컬 환경은 EnvironmentRecord 컴포넌트와 OuterLexicalEnvironmentReference 컴포넌트로 구성됨
- 전자는 스코프에 포함된 식별자를 관리하는 저장소. 소스코드의 타입에 따라 관리하는 내용에 차이 존재
- 후자는 상위 스코프(상위 코드의 렉시컬 환경)를 참조. 단방향 스코프 체인을 구현
실행 컨텍스트 생성과 식별자 검색 과정
과정 일반화
- 코드 평가
- 실행 컨텍스트 생성
- 렉시컬 환경 생성
- 환경 레코드 생성
- this바인딩
- 외부 렉시컬 환경 참조 결정
- 코드 실행
실제 과정
- 전역 객체 생성
- 전역 코드 평가
- 전역 실행 컨텍스트 생성
- 전역 렉시컬 환경(global lexical environment) 생성
- 전역 환경 레코드(global environment record) 생성
- 객체 환경 레코드(object environment record) 생성
- 선언적 환경 레코드(declarative environment record) 생성
- this 바인딩
- 외부 렉시컬 환경 참조(outer lexical environment reference) 결정
- 전역 환경 레코드(global environment record) 생성
- 전역 코드 실행
(4. 함수 코드 평가 및 실행)
각 과정의 설명
- 전역 객체 생성
- 빌트인 전역 프로퍼티, 빌트인 전역 함수, 표준 빌트인 객체, 호스트 객체 추가
- 전역 객체는 최상위 객체이지만 Object.prototype을 상속 받음. 최상위 객체라는 말은 어느 객체의 프로퍼티가 아님을, 즉 어느 객체에도 속하지 않는다는 뜻임
console.log(globalThis.toString()); // [object global]
console.log(globalThis.hasOwnProperty('toString')); // false
console.log(globalThis.hasOwnProperty('console')); // true
- 전역 코드 평가
- 전역 실행 컨텍스트 생성
- 전역 실행 컨텍스트를 생성해 실행 컨텍스트 스택(콜 스택)에 푸시
- 전역 렉시컬 환경(global lexical environment) 생성
- 전역 렉시컬 환경을 생성하고 전역 실행 컨텍스트에 바인딩. 전역 환경 레코드와 외부 렉시컬 환경 참조로 구성됨
- 전역 환경 레코드(global environment record) 생성
- 전역 스코프, 전역 객체, 표준 빌트인 객체를 제공
- 객체 환경 레코드(object environment record) 생성
- BindingObject라 불리는 객체(전역 객체)와 연결됨
- BindingObject를 통해 전역 var로 선언한 전역 변수와 함수 선언문으로 정의된 전역 함수를 전역 객체의 프로퍼티와 메서드로 바인딩 시킴
- 선언적 환경 레코드(declarative environment record) 생성
- let, const 키워드로 선언한 전역 변수를 관리
- this 바인딩
- 전역 환경 레코드의 [[GlobalThisValue]] 내부 슬롯에 this가 바인딩 됨.
- 일반적으로 전역 코드에서 this는 전역 객체를 가리킴
- 외부 렉시컬 환경 참조(outer lexical environment reference) 결정
- 전역 코드의 상위 스코프가 존재하지 않으므로 null
- 전역 렉시컬 환경이 스코프 체인의 종점
- 전역 실행 컨텍스트 생성
- 전역 코드 실행
- 식별자 결정(identifier resolution) : 식별자가 어느 스코프의 식별자인지 결정하는 것
- 식별저 결정을 위해 식별자 검색 시 실행 중인 실행 컨텍스트에서 식별자를 검색 시작해서 스코프 체인(외부 렉시컬 환경 참조, 상위 스코프)을 타고 검색함
(4. 함수 코드 평가 및 실행)
- 각 함수가 실행 종료가 되어 콜스택에서 해당 함수의 실행 컨텍스트가 제거되었다고 해서 해당 함수의 렉시컬 환경까지 즉시 소멸되는 것은 아님.
- 렉시컬 환경은 실행 컨텍스트에 의해 참조되지만 독립적인 객체이므로 다른 누군가가 렉시컬 환경을 참조하고 있다면 해당 랙시컬 환경은 소멸되지 않음
실행 컨텍스트와 블록 레벨 스코프
- let과 const는 모든 코드 블록(함수를 포함한 if문, for문, while문, try/catch문 등)을 지역 스코프로 인정하는 블록 레벨 스코프를 따름
- 코드 블록이 실행 되면 블록 레벨 스코프를 생성해야 함
- 이를 위해 선언적 환경 레코드를 갖는 렉시컬 환경을 새롭게 생성하고 기존의 전역 렉시컬 환경을 교체함
- 교체된 렉시컬 환경의 외부 렉시컬 환경 참조에는 기존의 전역 렉시컬 환경이 바인딩됨
'Programming > Javascript' 카테고리의 다른 글
클래스 (0) | 2021.10.13 |
---|---|
클로저 (0) | 2021.10.11 |
this (0) | 2021.10.06 |
빌트인 객체 (0) | 2021.10.05 |
strict mode (0) | 2021.10.04 |
Comments