잔디를 클릭하면 내용확인이 가능합니다.
모자딥 실행컨텍스트
- 자바스크립트 동작 원리를 담고 있는 핵심 개념
- EcmaScript 사양에서는 4가지 타입으로 구분
- 전역 코드, 함수 코드, eval 코드, 모듈 코드
자바스크립트 엔진은 소스코드 평과와 실행 과정으로 나누어서 처리한다.
실행 컨텍스트의 역할
전역 코드 평가 : -> 전역 코드 실행 -> 함수 코드 평가 -> 함수 코드 실행
그냥 해당 스코프에 있는 함수, 변수가 순차적으로 평가 -> 실행 되는 과정, 그 과정에서 내부 스코프가 있는 영역이 호출된다면, 해당하는 함수 스코프로 포커스를 이동하고 함수 평가 -> 실행, 함수 호출이 종료된다면 이전으로 돌아가기 위해 현재 실행하는 코드, 이전 실행하던 코드를 구분해야한다 => 스코프, 식별자, 코드 실행 순서와 같은 관리가 필요하다
- 선언에 의해 생성된 모든 식별자를 스코프를 구분하여 등록하고, 상태변화를 지속적으로 관리할 수 있어야 한다
- 스코프 중첩 관계에 의해서 스코프 체인을 형성해야한다. 스코프 체인을 통해 상위 스코프 이동하여 식별자를 검색할 수 있어야 한다
- 현재 실행중인 코드의 실행 순서를 변경할 수 있어야한다. => 이 모든 것들을 관리하는것이 바로 실행 컨텍스트, 실행 컨텍스트는 소스 코드를 실행하는데 필요한 환경을 제공하고 코드의 실행 결과를 실제 관리하는 영역
식별자, 스코프는 렉시컬 환경 코드 실행 순서는 실행 컨텍스트 스택으로 관리한다
렉시컬 환경
렉시컬 환경은 식별자와 식별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트이다.
- 키 밸류 형태의 스코프를 생성해, 식별자를 키로 등록하고 식별자에 바인딩된 값을 관리 실행 컨텍스트는 렉시컬 환경 컴포넌트와, 변수환경 컴포넌트로 구성
=> 그래서 그게 뭔데? 렉시컬 환경 컴포넌트와 변수 환경 컴포넌트는 하나의 동일한 렉시컬 환경을 참조한다
렉시컬 환경은 다음 두 개의 컴포넌트로 구성
- 환경 레코드
- 스코프에 포함된 식별자를 등록하고 식별자 바인딩된 값을 관리하는 저장소. 환경 레코드는 소스코드의 타입에 따라 관리하는 내용에 차이가 있다
- 외부 렉시컬 환경에 대한 참조
- 상위 스코프를 가리킨다. 상위 스코프는 외부 렉시컬 환경. 해당 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 코드의 렉시컬 환경. 외부 렉시컬 환경에 대한 참조를 통해 단방향 링크드 리스트인 스코프 체인 구현
실행 컨텍스트의 생성과 식별자 검색 과정
- 전역 객체 생성 전역 객체는 전역 코드가 평가되기 이전에 생성. 빌트인 전역 프로퍼티, 빌트인 전역 함수, 표준 빌트인 객체가 추가 동작 환경에 따른 WebAPI 및 호스트 객체 포함한다 전역 객체도 오브젝트 프로토타입을 상속받는다, 전역 객체도 프로토타입 체인의 일원이다.
- 전역 코드 평가 소스코드가 로드되면 js 엔진은 전역 코드를 평가.
1. 전역 실행 컨텍스트 생성
2. 전역 렉시컬 환경 생성
- 전역 환경 레코드 생성
- 객체 환경 레코드 생성
- 선언적 환경 레코드 생성
3. 디스 바인딩
4. 외부 렉시컬 환경에 대한 참조 결정
실행 컨텍스트 중 최상위 => 실행 중인 실행 컨텍스트 실실컨 렉시컬 환경은 => 환경 레코드와, 외부 렉시컬 환경 참조 두개로 분리
전역 환경 레코드는 전역 변수 관리하는 전역 스코프, 전역 객체의 빌트인 전역 프로퍼티, 빌트인 전역함수, 표준 빌트인 객체 제공 ?? 이거 전역 객체 초반에 생성하는거 아니었음 했는데 전역 환경 레코드에서 객체 환경 레코드로서 제공하는 값들은 전역 객체와 바인딩이 되어서 제공하는 것.
전역 코드 평가
2.1.1 객체 환경 레코드 전역 환경 레코드는 객체 환경 레코드와 선언적 환경 레코드로 구분되는데 전자의 경우에는 var나 window 객체와 바인딩. 그래서 var 쓰면 window로 접근이 가능한 이유. 선언적 환경 레코드는 let, const로 전역환경 레코드의 스코프 범위가 다름. 객체 환경 레코드는 바인딩 오브젝트라는 객체와 연결되는데 (= 전역 객체 생성때 생성) 요놈떄문에 var 키워드와 전역 함수는 전역 객체의 프로퍼티나 메소드가 된다. var키워드나 함수 선언문을 통해 정의된 전역 함수가 전역 객체를 참조할 수 있는 메커니즘
지금은 전역 코드 평가 과정이니, 이 과정을 통해 var는 실행 이전에도 참조가 가능하다 ( 전역 객체로 바인딩 오브젝트를 통해서 연결되니까 ) 이러면 코드 실행 단계 이전에 var에 선언되어 있음 => 변수 호이스팅이 발생하는 원인. 단 변수 선언문 이전에 참조한 변수의 값은 언디파인드, 함수 선언문으로 정의된 함수가 평가되면 동일하게 바인딩된 바인딩 오브젝트를 통해 즉시 할당이 가능. 이건 접근도 가능, 이것이 변수 호이스팅 undefined와 함수 호이스팅 즉시 실행의 차이. 변수 var a= 3 인 경우, 평가 단계에서는 var 은 선언까지만 함, 실행 단계에서 이 값에 3이 할당되어지니까 차이가 있다는 것!
2.1.2 선언적 환경 레코드 var 이외 전역 변수나 let const를 통해 할당한 함수 표현식의 경우 선언적 환경 레코드에 등록. 이거는 전역 객체의 프로퍼티가 아닌 "개념적 블록" 그래서 전역객체가 아님. 그래서 초기화 단계와 선언 단계가 분리되어 진행하니 이것이 TDZ, 코드 실행 단계에서 할당 되어지기 전까지의 일시적 사각지대. 호이스팅이 발생하는것은 변함이 없지만 undefined로 할당이 안되었기에 참조할 수 없는 것
2.2 this 바인딩
전역 환경 레코드의 내부 슬롯에 this가 바인딩 됨. 일반적으로 전역 코드 this는 전역 객체를 가리키므로 전역 환경 레코드의 [[GlobalThisValue]] 슬롯에는 전역 객체가 바인딩. 그니까 전역 환경 레코드의 this는 전역 객체를 가리킨다.

2.3 외부렉시컬 환경에 대한 참조 결정 외부 렉시컬 환경에 대한 참조는 현재 평가 중인 소스코드를 포함하는 외부 소스코드 렉시컬 환경, 상위 스코프를 가리킨다. 요게 스코프체인
전역 코드 실행
위에서부터 순차적으로 선언된 값에 대한 할당, 평가 시작. 실행중인 실행 컨텍스트 영역 내에서 작업 이때 찾으려는 식별자가 해당 스코프가 없다면 외부 렉시컬 환경을 통해 상위 스코프체인으로 이동, 이것이 스코프 체인의 동작 원리. 전역 레시컬 환경에서 못 찾는다면 Reference Error,요게 끝이여서.
함수 코드 평가
1. 함수 실행 컨텍스트 생성
2. 함수 렉시컬 환경 생성
- 함수 환경 레코드 생성
- 디스 바인딩
- 외부 렉시컬 환경에 대한 참조 결정

-
함수 실행 컨텍스트 생성 함수 실행 컨텍스트 생성. 생성된 함수 실행 컨텍스트는 함수 렉시컬 환경이 완성된 다음 실행 컨텍스트에 푸시 실실컨 => 함실컨
-
함수 렉시컬 환경 생성 함수 렉시컬 환경 생성하고 실행 컨텍스트에 바인딩 렉시컬 환경은 2개의 컴포넌트, 그리고 외부 렉시컬 환경 참조로 구성
2.1 함수 환경 레코드 생성 함수 렉시컬 환경을 구성하는 컴포넌트, 함수 환경 레코드, 매개 변수나 함수, 함수 내부에서 선언한 변수 지역변수 중첩 함수 등을 등록하고 관리
2.2 디스바인딩 호출 방식에 따라 디스바인딩이 달라지는데, 일반 함수에서 호출 되는 경우에는 전역 객체에 바인딩
2.3 외부 렉시컬 환경에 대한 참조 결정 자바스크립트는 함수를 어디서 호출했는지가 아니라, 어디에 정의했는지에 따라 상위 스코프를 결정한다. 자신이 정의된 스코프 즉 상위 스코프를 기억하는데 함수 객체를 생성할 떄, 현재 실행 중인 실행 컨텍스트의 렉시컬 환경, 함수의 상위 스코프를 함수 객체 내부 슬롯 environment에 저장한다. 즉 함수 렉시컬 환경의 외부 렉시컬 환경 참조에 할당 되는 것은 상위 스코프의 저장된 렉시컬 환경에 참조. 이것이 렉시컬 스코프를 구현하는 메커니즘이고, 클로저를 이해할 수 있는 단서

- 현재 실행중인 실행 컨텍스트 bar에서 console.log를 실행한다고 했을때, 상위에서부터 스코프체인을 타고 이동. bar 의 렉시컬 환경에서는 console이 정의되어지지 않음, 그러면 외부 렉시컬 환경 참조가 가리키는 방향 foo로 이동 근데 거기도 업슴 -> 전역으로 이동 전역 렉시컬 환경에서ㅏ의 객체 환경 레코드 내에서 window 객체를 참조하고 있어 여기서 찾는거임