1. 실행컨텍스트란?1.1 정의1.2 생성시점2. 실행컨텍스트 구성요소2.1 VariableEnvironment2.2 LexicalEnvironment2.3 This3. EnvironmentRecord와 호이스팅3.1 호이스팅 이란3.2 사례를 통해 호이스팅 이해/점검하기4. Scope와 스코프체인, OuterEnvironmentReference4.1 스코프, 스코프체인 이란4.2 OuterEnvironmentReference4.3 사례를 통해 이해/점검하기** This와 Closer는 별도의 포스팅으로참고
1. 실행컨텍스트란?
1.1 정의
- 실행컨텍스트는 “실행할 코드에 제공할 환경정보들을 모아놓은 객체" 이다.
- 실행컨텍스트는 생성 시 “콜스택”에 쌓아올려지고, 가장 위의 컨텍스트와 관련 있는 코드들을 실행하는 방식으로 “전체코드의 환경과 순서를 보장”한다.
1.2 생성시점
- 실행컨텍스트는 4가지 방법을 통해 생성될 수 있다.
전역컨텍스트
는 자동으로 생성된다.함수
실행 시eval()
함수 실행 시- ES6+의
block
생성 시()
- 실행컨텍스트가 생성(활성화) 되는 시점에서 발생하는 일
- 선언된 변수들을 끌어 올린다.
호이스팅
- 외부 환경 정보 구성 (
LexicalEnviroment의 OuterEnvironmentReference
) - this의 값을 설정
2. 실행컨텍스트 구성요소
실행컨텍스트 구성요소
VariableEnvironment : environmentRecord + outerEnvironment (
스냅샷
)
LexicalEnvironment : environmentRecord + outerEnvironment
ThisBinding2.1 VariableEnvironment
- 실행컨텍스트 생성 시 가장 먼저 생성됨
- EnvironmentRecord + OuterEnvironmentReference
- 생성 이후, 그대로 복사하여 LexicalEnvironment 를 생성
- 최초 실행 시의 정보만을 가지고, 이후에 변화된 정보를 담아내지 못함
스냅샷
- *실제 JS엔진에서는 VariableEnvironment보다 LexicalEnvironment를 주로 활용함
2.2 LexicalEnvironment
현재 컨텍스트의 내부 식별자 정보 (EnvironmentRecord)와
외부 컨텍스트의 정보 (OuterEnvironmentReference)를 가지고 있음
- 첫 생성 시는 VariableEnvironment와 같음
- EnvironmentRecord + OuterEnvironmentReference
- 변경사항이 실시간으로 즉각 반영됨
- EnviromentRecord로 인하여 호이스팅이 발생한다.
- OuterEnvironmentReference로 인하여 스코프와 스코프체인이 형성된다.
2.3 This
- 별도 포스팅
3. EnvironmentRecord와 호이스팅
3.1 호이스팅 이란
- EnvironmentRecord에는 현재 컨텍스트와 관련된 코드의 “식별자 정보”들이 저장된다.
- 함수의 매개변수 식별자(arguments)
- 함수 선언 시, 함수 그 자체
- 변수의 식별자 (var, let, const)
- EnvironmentRecord가 생성이 완료되는 시점은, 실제 코드가 실행되기 이전이다.
- 코드가 실행 하기 전, “js엔진은 식별자들을 최상단으로 끌어올려 놓은 다음 실제 코드를 실행”하게 됨
- 이를 가상의 개념인 호이스팅이라고 지칭함
- 실제로 끌어올리지는 않지만, 그런 것 같이 동작하므로, 끌어올린 것으로 간주하는 것
3.2 사례를 통해 호이스팅 이해/점검하기
- [1번 예제]
답안 및 풀이
(1): 1 (2): 1 (3) 2
- 매개 변수는 호이스팅 이전, 최상단에서 선언/할당하는 것과 같이 동작한다.
- 호이스팅 이후, 코드 동작
4. Scope와 스코프체인, OuterEnvironmentReference
4.1 스코프, 스코프체인 이란
- 스코프는 “식별자에 대한 유효범위”
- 스코프체인이란 ”식별자에 대한 유효범위(
스코프
)를 안에서 부터 바깥으로 차례대로 검색해나가는 것”
- 스코프체인을 가능하게 하는 것은 LexicalEnvironment의 OuterEnviromentReference 이다.
4.2 OuterEnvironmentReference
- OuterEnvironmentReference는 현재 호출된 함수가 “선언된 순간”의 LexicalEnvironment를 참조한다.
선언하다
라는 행위가 실제로 일어날 수 있는 시점은 콜 스택 상에서 어떤 실행 컨텍스트가 활성화된 상태일 때뿐이다. 모든 코드는 실행 컨텍스트가 활성화 상태일 때 실행되기 때문이다.- 선언된 순간의 LexicalEnvironment는 현재 호출된 함수를 기준으로 바로 위의 컨텍스트의 LexicalEnvironment를 의미한다.
- 내부 함수에서는 외부함수의 스코프에 접근할 수 있으나, 외부함수에서는 내부 함수의 스코프에 접근할 수 없다.
- 여러 스코프에서 동일한 식별자를 선언할 경우, 무조건 해당 scope chain에서 가장 먼저 발견된 식별자에만 접근할 수 있게 된다.
- 전역에도 a 식별자가 존재하지만, inner함수에서는 inner 컨텍스트의 식별자 a에만 접근가능하다.
4.3 사례를 통해 이해/점검하기
- 예제
- (0) 전역 컨텍스트 생성
- 호이스팅을 통해 environmentRecord에
{ a, outer }
식별자 정보를 저장
- (1) ⇒ (2) outer 컨텍스트 생성
- outer함수가 호출
(1)
- outer 컨텍스트의 environmentRecord에
{ inner }
식별자 정보가 저장 - outer 컨텍스트의 outerEnvironmentReference에 outer함수 선언된 순간의 컨텍스트인 전역컨텍스트의 LexicalEnvironment인
[전역, { a , outer }]
가 저장된다. - outer컨텍스트의 outerEnvironmentReference =
[전역컨텍스트, { a, outer }]
- (3) ⇒ (4) inner 컨텍스트 생성
- inner 함수가 호출
(3)
- inner 컨텍스트의 environmentRecord에
{ a }
식별자 정보가 저장 - inner 컨텍스트의 outerEnvironmentReference =
[ outer, { inner } ]
정보가 저장
- (5) console.log(a)
- 현재 컨텍스트인 inner 컨텍스트의 envirionmentRecord에서 a를 찾아 반환하게 됨
- 할당된 값이 없으므로 “
undefined
출력”
- (6) var a = 3
- inner 스코프에 존재하는 변수 a에 3을 할당
- inner 컨텍스트가 종료 되고, 다시 outer컨텍스트의 코드가 마저 실행 됨
- (7) console.log(a)
- outer 컨텍스트의 environmentRecord에서 a를 탐색 ⇒ 없음
- outer 컨텍스트의 outerEnvironmentReference의 environmentRecord 에서 a 탐색 ⇒ 전역스코프의 a 반환
- 전역 스코프의 a의 할당 값인 1이 반환
- outer컨텍스트 종료
- (8) console.log(a)
- 전역 컨텍스트의 environmentRecord에서 a를 탐색 ⇒ 발견 후 할당된 값인 1을 반환
** This와 Closer는 별도의 포스팅으로
⇒ Go This
⇒ Go Closer
참고
- 코어자바스크립트