23. 실행 컨텍스트
in 모던자바스크립트
- 목차
1. 소스코드의 타입
- 소스코드 구분 이유 : 소스코드 타입에 따라 실행 컨텍스트를 생성하는 과정, 관리 내용이 달라서
- 전역코드
- 함수, 클래스 내부 코드는 x
- 전역 변수를 관리하기 위해 최상위 스코프인 전역 스코프를 생성해야 한다.
- var 키워드로 선언된 전역 변수와 함수선언문으로 정의된 전역 함수를 전역객체의 프로퍼티와 메서드로 바인딩하고 참조하기 위해, 전역객체와 연결해야 한다.
- 이를 위해 전역 코드가 평가되면 전역 실행 컨텍스트가 생성된다.
- 함수코드
- 중첩된 함수, 클래스 내부 코드는 x
- 지역 스코프를 생성
- 지역 변수, 매개변수, arguments 객체를 관리
- 생성한 지역 스코프를 전역 스코프에서 시작하는 스코프 체인의 일원으로 연결
- 함수 코드가 평가되면 함수 실행 컨텍스트가 생성
- eval 코드
- strict mode에서 자신만의 독자적인 스코프를 실행
- eval 코드가 평가되면 eval 실행 컨텍스트가 생성
- 모듈 코드
- 모듈별로 독립적인 모듈 스코프 생성
2. 소스코드의 평가와 실행
- 소스 코드 평가 과정
- 실행 콘텍스트 생성
- 변수, 함수 등의 선언문만 먼저 실행 > 생성된 변수, 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프(렉시컬 환경의 환경 레코드)에 등록
- 소스 코드 실행 과정
- 선언문을 제외한 소스코드가 순차적으로 실행
- 런타임 시작
- 소스코드 실행에 필요한 정보(변수, 함수의 참조)를 실행 컨텍스트가 관리하는 스코프에서 검색해 취득
- 변수 값의 변경 등 소스코드의 실행 결과는 실행 컨텍스트가 관리하는 스코프에 등록
3. 실행 컨텍스트의 역할
- 코드가 실행되려면 스코프, 식별자, 코드 실행 순서 등의 관리가 필요하다
- 선언에 의해 생성된 모든 식별자를 스코프로 구분하여 등록하고, 상태변화를 지속적으로 관리한다.
- 스코프는 중첩 관계에 의해 스코프 체인을 형성한다. > 스코프 체인을 통해 상위 스코프로 이동하며 식별자를 검색할 수 있어야 한다.
- 현재 실행중인 코드의 실행 순서를 변경할 수 있어야 하며, 다시 되돌아갈 수 있어야 한다.
- 실행 컨텍스트는 소스코들르 실행하는데 필요한 환경을 제공하고, 코드의 실행 결과를 실제로 관리하는 영역
- 식별자를 등록하고 관리하는 스코프 + 코드 실행 순서 관리를 구현한 내부 메커니즘으로, 모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다.
- 렉시컬 환경 : 식별자와 스코프
- 실행 컨텍스트 스택 : 코드 실행 순서
4. 실행 컨텍스트 스택
- 실행 컨텍스트 스택은 코드의 실행 순서를 관리
- 소스코드가 평가되면 실행 컨텍스트 생성 > 스택에 push
- 실행 컨텍스트 스택 최상위에 존재하는 실행 컨텍스트는 언제나 현지 실행 중인 코드의 실행 컨텍스트
- 실행 컨텐스트 스택의 최상위 실행 컨텍스트 : 실행중인 실행 컨텍스트
5. 렉시컬 환경
- 식별자와, 식별자에 바인딩 된 값, 상위 스코프에 대한 참조를 기록하는 자료구조
- 실행 컨텍스트를 구성하는 컴포넌트
- 스코프와 식별자를 관리
- 키-값을 갖는 객체 형태의 스코프 생성 > 식별자를 키로 등록하고 식별자에 바인딩된 값을 관리
- 렉시컬 환경 : 스코프를 구분하여 식별자를 등록하고 관리하는 저장소 역할을 하는 렉시컬 스코프의 실체
- 실행 컨텍스트 = LexicalEnvironment 컴포넌트 + VariableEnvironment 컴포넌트
- 이 둘은 초기에 Lexial Envirmonment 가리킴
- 렉시컬 환경 = EnvironmentRecord(환경 레코드) + OuterLexicalEnvironmentReference(외부 렉시컬 환경에 대한 참조)
- 환경 레코드 : 스코프에 포함된 식별자를 등록하고, 등록된 식별자에 바인딩된 값을 관리하는 저장소
- 외부 렉시컬 환경에 대한 참조 : 상위 스코프를 가리킨다. (상위 코드의 렉시컬 환경) > 링크드 리스트 스코프 체인 구현
6. 실행 컨텍스트의 생성과 식별자 검색 과정
var x = 1;
const y = 2;
function foo(a) {
var x = 3;
const y = 4;
function bar(b) {
const z = 5;
console.log(a + b + x + y + z);
}
bar(10);
}
foo(20);
전역 객체 생성
- 전역 객체는 전역 코드가 평가되기 이전에 생성
- 전역 객체도 Object.prototype 상속받는다. > 전역객체도 프로토타입 체인의 일원이다.
전역 코드 평가
전역 실행 컨텍스트 생성
- 실행 컨텍스트 스택에 push
전역 렉시컬 환경 생성
- 전역 실행 컨텍스트에 바인딩
전역 환경 레코드 생성
- 전역 환경 레코드 : 전역 변수를 관리하는 전역 스코프, 전역 객체의 빌트인 전역 프로퍼티, 빌트인 전역 함수, 표준 빌트인 객체 제공
- 전역 환경 레코드 = 객체 환경 레코드, 선언적 환경 레코드로 분류 (전역변수 var, let+const 구분 위해)
- 객체 환경 레코드 : var 키워드로 선언한 전역 변수, 함수 선언문, 빌트인 전역 프로퍼티, 빌트인 전역함수, 표준 빌트인 객체 관리
- 선언적 환경 레코드 : let, const 키워드로 선언한 전역 변수 관리
- 전역 환경 레코드의 객체 환경 레코드와 선언적 환경 레코드는 서로 협력하여, 전역 스코프와 전역 객체(전역 변수의 전역 객체 프로퍼티화)를 관리
객체 환경 레코드 생성
- BindingObject 객체(전역 객체)와 연결된다.
- 전역 코드 평가 과정에서, var 키워드로 선언한 전역 변수와 함수 선언문으로 선언한 전역 함수는 전역 환경 레코드의 객채 환경 레코드에 연결된 BindingObejct를 통해 전역 객체의 프로퍼티와 메서드가 된다.
선언적 환경 레코드 생성
- let, const 키워드로 선언한 전역변수는 선언적 환경 레코드에 등록, 관리
- 선언단계와 초기화 단계가 분리되어 진행된다. > 일시적 사각 지대에 빠진다 (uninitialized)
this 바인딩
- 전역 환경 레코드의 [[GlobalThisVallue]] 의 내부 슬롯에 this가 바인딩된다.
- 일반적으로 전역 객체가 바인딩
- 전역 환경 레코드를 구성하는 객체,선언적 환경 레코드에는 this 바인딩 없다.
- this 바인딩은 전역 환경 레코드와 함수 환경 레코드에만 존재
외부 렉시컬 환경에 대한 참조 결정
- 현재 평가중인 소스코드를 포함하는 외부 소스코드의 렉시컬 환경(상위 스코프)를 가리킨다.
- 이를 통해 단방향 링크드 리스크인 스코프 체인 구현
전역 코드 실행
- 어느 스코프의 식별자를 참조하면 되는지 결정하는 것 : 식별자 결정
- 식별자 결정을 위해 식별자를 검색할 때는, 실행 중인 실행 컨텍스트에서 식별자를 검색하기 시작
foo 함수 코드 평가
함수 실행 컨텍스트 생성
- foo 함수 실행 컨텍스트 생성. 생성된 함수 실행 컨텍스트는 함수 렉시컬 환경이 완성된 다음 실행 컨텍스트 스택에 push
함수 렉시컬 환경 생성
- foo 함수 렉시컬 환경을 생성하고 foo 함수 실행 컨텍스트에 바인딩
함수 환경 레코드 생성
- 매개변수, arguments 객체, 함수 내부에서 선언한 지역 변수와 중첩 함수를 등록, 관리
this 바인딩
- 함수 환경 레코드의 [[ThisValue]] 내부 슬롯에 this가 바인딩된다. > 호출 방식에 따라 결정
- foo 는 일반 함수로 호출 > 전역 객체
- foo 함수 내부에서 this 를 참조하면 함수 환경 레코드의 [[ThisValue]] 내부 슬롯에 바인딩되어있는 객체 반환
외부 렉시컬 환경에 대한 참조 결정
- foo 함수 정의가 평가된 시점에 실행 중인 실행 컨텍스트의 렉시컬 환경의 참조가 할당
- foo 는 전역 코드에서 정의된 전역 함수 > 전역 렉시컬 환경의 참조가 할당
- js는 함수 정의를 평가하여 함수 객체 생성할 때, 현재 실행 중인 실행 컨텍스트의 렉시컬 환경, 즉 함수의 상위 스코프를 함수 객체의 내부 슬롯 [[Environment]]에 저장
- 힘수 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 할당되는 것 : 함수의 상위 스코프를 가리키는 함수 객체의 내부 슬롯 [[Environment]] > 렉시컬 스코프를 구현하는 메커니즘
foo 함수 코드 실행
bar 함수 코드 평가
bar 함수 코드 실행
- console 식별자 검색
- log 메서드 검색
- 표현식 a + b + x + y + z 평가
- console.log 메서드 호출
bar 함수 코드 실행 종료
- 실행 컨텍스트 스택에서 bar 함수 실행 컨텍스트 pop
- bar 함수 렉시컬 환경까지 즉시 소멸하는 건 아님
- 렉시컬 환경은 실행 컨텍스트에게 참조되기는 하지만 독립적 객체
- bar 함수 실행 컨텍스트가 소멸되었더라도, 만약 bar 함수 렉시컬 환경을 누군가 참조한다면 bar 함수 렉시컬 환경은 소멸 x
foo 함수 코드 실행 종료
전역 코드 실행 종료
7. 실행 컨텍스트와 블록 레벨 스코프
- var : 함수 레벨 스포크
- let, const : 블록 레벨 스코프