일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 뷰
- 예외처리
- css
- 프론트엔드
- 자바스크립트 #javascript #렌더링 #렌더링순서
- cubic-bezier
- DOM
- frontend
- 로컬스토리지
- vue-router
- vuetify
- 성능 최적화
- Transition
- jest
- webpack
- vue #vue.js #font #web-font
- lazy loading
- 렌더링 최적화
- vue.js
- 세션스토리지
- 세션
- NavigationDuplicated
- 주니어 개발자
- 라우터
- virtual dom
- Django
- 안드로이드
- VUE
- 장고
- Router
- Today
- Total
한준호
[Modern javascript] 실행 컨텍스트(2) 본문
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을 상속받는다.
■ 전역 코드 평가
- 소스코드가 로드되면 자바스크립트 엔진은 전역 코드를 평가하고 다음과 같은 순서를 가진다.
- 전역 실행 컨텍스트 생성
- 전역 렉시컬 환경 생성
- 전역 환경 레코드 생성
- 객체 환경 레코드 생성
- 선언적 환경 레코드 생성
- this 바인딩
- 외부 렉시컬 환경에 대한 참조 결정
- 전역 환경 레코드 생성
1. 전역 실행 컨텍스트 생성
- 전역 실행 컨텍스트를 생성하여 실행 컨텍스트 스택에 푸시
2. 전역 렉시컬 환경 생성
- 전역 렉시컬 환경 생성하여 전역 실행 컨텍스트에 바인딩
- 전역 렉시컬 환경은 환경 레코드와 외부 렉시컬 환경에 대한 참조로 구성된다.
2.1 전역 환경 레코드 생성
- 객체 환경 레코드(var), 선언적 환경 레코드(let, const)로 구성된다.
2.1.1 객체 환경 레코드 생성
- 전역 코드 평가 과정에서 var 키워드로 선언한 전역 변수와 함수 선언문으로 정의된 전역 함수는 전역 환경 레코드의 객체 환경 레코드에 연결된 BindingObject를 통해 전역 객체의 프로퍼티와 메서드가 된다.
- 함수 선언문으로 정의된 함수는 BindingObject를 통해 전역 객체에 키로 등록하고 생성된 함수 객체를 즉시 할당하지만 var로 선언된 변수는 undefined를 할당한다.
2.1.2 선언적 환경 레코드 생성
- 함수 호이스팅이 발생하는 것은 맞지만 선언 단계와 초기화 단계까 분리되어 진행되므로 일시적 사각지대가 존재한다.
2.2 this 바인딩
- 전역 환경 레코드의 [[GlobalThisValue]] 내부 슬롯에 this가 바인딩된다. 일반적으로 전역 환경 레코드엔 전역 객체가 바인딩된다.
- 전역 환경 레코드를 구성하는 객체 환경 레코드와 선언적 환경 레코드엔 this 바인딩이 없다
2.3 외부 렉시컬 환경에 대한 참조 결정
- 상위 스코프를 가리킨다.
■ 전역 코드 실행
전역 코드가 실행되면 변수 할당문이 실행되어 전역 변수 x, y에 값이 할당되고 foo함수가 호출된다.
-> foo함수를 호출하는 코드에 도달하면 해당하는 식별자가 스코프 내에 존재하는지 찾는다.
-> 식별자 결정을 위해 식별자를 검색할 때는 실행중인 컨텍스트에서 식별자를 검색한다.
-> 현재 실행 컨텍스트는 전역 실행 컨텍스트이므로 전역 렉시컬 환경에서 식별자 x, y, foo를 검색한다.
-> 실행 컨텍스트 렉시컬 환경에서 식별자를 검색할 수 없으면 외부 렉시컬 환경 참조가 가리키는 렉시컬 환경, 즉 상위 스코프로 이동하여 식별자를 검색한다.
■ foo 함수 코드 평가
- 함수 코드 평가는 다음과 같은 순서를 가진다.
- 함수 실행 컨텍스트 생성
- 함수 렉시컬 환경 생성
- 함수 환경 레코드 생성
- this 바인딩
- 외부 렉시컬 환경에 대한 참조 결정
1. 함수 실행 컨텍스트 생성
- foo함수 실행 컨텍스트를 생성하고 실행 컨텍스트 스택에 푸시되어 실행 컨텍스트가 된다.
2. 함수 렉시컬 환경 생성
- foo 함수 렉시컬 환경을 생성하고 foo 함수 실행 컨텍스트에 바인딩한다.
2.1 함수 환경 레코드 생성
- 함수 환경 레코드는 매개변수, arguments 객체, 함수 내부의 지역 변수와 중첩 함수를 등록하고 관리한다.
2.2 this 바인딩
- 함수 환경 레코드의 [[GlobalThisValue]] 내부 슬롯에 this가 바인딩된다.
- foo 함수는 일반 함수로 호출되었으므로 this는 전역 객체를 가리킨다.
- 함수 환경 레코드의 [[ThisValue]] 내부 슬롯에는 전역 객체가 바인딩 되고, 따라서 foo 함수 내에서 this를 참조하면 [[ThisValue]] 내부 슬롯에 바인딩되어 있는 객체가 반환된다.
2.3 외부 렉시컬 환경에 대한 참조 결정
- foo 함수는 전역 코드에 정의된 함수이므로 외부 렉시컬 환경 참조에는 전역 렉시컬 환경이 할당된다.
- 자바스크립트는 함수를 어디서 호출했는지가 아니라 어디서 정의했는지에 따라 상위 스코프를 결정한다.
- 함수의 상위 스코프를 함수 객체 내부 슬롯 [[Environment]]에 저장한다. 즉 함수 객체의 내부 슬롯 [[Environment]]가 렉시컬 스코프를 구성하는 메커니즘이다.
■ foo 함수 코드 실행
- 식별자 결정을 위해 실행 중인 컨텍스트의 렉시컬 환경에서 식별자를 검색한다.
-> foo 함수 렉시컬 환경에서 식별자 x, y를 검색한다.
■ bar 함수 코드 평가
- foo 와 동일하게 작동
■ bar 함수 코드 실행
- console 식별자를 스코프 체인에서 찾는다(bar -> foo -> 전역). 전역 렉시컬 환경의 전역 객체에서 찾을 수 있다.
- log 메서드를 console 객체에서 프로토타입 체인을 통해 검색한다
- a는 foo, b는 bar, x와 y는 foo, z는 bar 함수 렉시컬 환경에서 검색된다.
■ bar 함수 코드 실행 종료 -> foo 함수 코드 실행 종료 -> 전역 코드 실행 종료
- 실행 컨텍스트 스택에서 차례대로 제거되는데, 함수 렉시컬 환경까지 즉시 소멸하는 것은 아니다. 객체를 포함한 모든 값은 누군가에 의해 참조되지 않을 때 비로소 가비지 컬렉터에 의해 메모리 공간의 확보가 해제되어 소멸한다. 즉 bar 함수 실행 컨텍스트가 소멸되었다고 해도 누군가 bar 함수 렉시컬 환경을 참조하고 있다면 bar 함수 렉시컬 환경은 소멸하지 않는다.
◎var 키워드는 함수 레벨 스코프를 가지는 반면 let, const 키워드는 블록 레벨 스코프를 가진다고 했다. 개념적인 블록 내에 존재하는 것인데 그 블록이 바로 선언적 환경 레코드이다.
'Frontend > modern javascript' 카테고리의 다른 글
[Modern javascript] 클래스(1) (0) | 2021.08.31 |
---|---|
[Modern javascript] 클로저 (0) | 2021.08.31 |
[Modern javascript] 실행 컨텍스트(1) (1) | 2021.08.28 |
[Modern javascript] this (0) | 2021.08.26 |
[Modern javascript] 빌트인 객체 (0) | 2021.08.26 |