01. 실행 컨텍스트란?
실행할 코드에 제공할 환경 정보들을 모아놓은 객체
- VariableEnvironment: 현재 컨텍스트 내의 식별자들 정보 + 외부 환경정보, LexicalEnviornment의 스냅샷
- LexicalEnvironmnet: VariableEnvironment와 같지만 변경사항이 실시간으로 반영됨
- ThisBinding: this 식별자가 바라봐야할 대상 객체
02. VariableEnvironment
실행 컨택스트를 생성할때 VariableEnvironment에 정보를 먼저 담고, 이를 복사해서 LexicalEnvironmnet를 만든다
03. LexicalEnvironment
수시로 변경하는 환경 정보
2-3-1 environmentRecord와 호이스팅
environmentRecord: 현재 컨택스트와 관련된 코드의 식별자 정보가 저장됨
var a = 1;
let b = 1;
const c = 4;
var meta = {
content:2,
props: "string"
}
function a() {}
호이스팅 규칙
코드가 실행되기 전에 엔진에서 환경에 사용된 변수 명을 수집(이해하기 쉽게, 변수를 최상단으로 끌어 올린다고 생각)
같은 컨택스트 내 선언된 변수, 함수를 hoisting 하고, 할당 시점에 해당 변수/함수를 할당한다.
function a(){
console.log(b);
var b = 'bbb'
console.log(b);
function b(){}
console.log(b);
}
2-3-2 스코프, 스코프 체인, outerEnvironmentReference
함수스코프: ES5에서는 함수에 의해서만 스코프가 생성됨; var
블록스코프: ES6에서는 블록에 의해서도 스코프 경계가 발생됨; let, const, class, strict mode
스코프 체인: 식별자 유효범위 안에서부터 바깥으로 차례로 검색해 나가는 것
아래와 같이 outer 함수 안에 inner 함수가 호출된 경우, inner함수의 outerEnvironmentReference는 outer함수의 LexicalEnvironment을 참조함
→ 무조건 스코프 체인상에서 가장 먼저 발견된 식별자에만 접근 가능함
var a = 1;
var outer = function(){
var inner = function(){
console.log(a)
var a = 3; (2)
}
inner();
console.log(a)
}
outer();
console.log(a)
- (1) 처럼 선언과 할당이 (결과)보다 위에 있을 경우엔, "3" 이 출력됨
- (2) 처럼 hoising으로 선언은 먼저 되고 (결과) 보다 할당이 나중에 될 경우 "undefined" 가 출력됨
- 만약 (1), (2) 가 주석 처리 되고, inner함수 컨텍스트에 a변수가 없는 경우: 스코프 체이닝을 통해 global 객체까지 해당 변수를 찾음
- inner함수 LexicalEnvironment의 environmentRecord에서 a 변수를 서치 → 없다면 아래 로직
- inner함수 LexicalEnvironment의 outerEnvironmentReference 즉, outer 함수의 LexicalEnvironment에서 a 변수를 찾음 → 없다면 아래 로직
- outer함수 LexicalEnvironment의 outerEnvironmentReference 즉, global 객체의 LexicalEnvironment에서 a 변수를 찾음 → 없다면 "undefined"
- 이 경우에는 (결과)에서 "1" 이 출력됨
변수은닉화(variable shadowing): inner함수에서 a 변수를 선언함으로써 전역 공간의 a 변수 접근을 막음
var name = 'a';
function a(){
console.log(name)
}
function b(){
name = 'b'
a()
}
b();
04. this
thisBinding에는 this로 지정된 객체가 저장됨. 실행 컨택스트 활성화 당시에 this가 지정되지 않은 경우, this는 전역 객체가 저장됨.
05. 정리
- 실행 컨텍스트
- 현재 실행할 코드에 바라보아야 할 환경 정보를 담고 있는 객체
- LexicalEnvironment
- 수시로 변경되는 환경 정보를 담은 객체
- environmentRecord
- 현재 컨텍스트에서 바라보아야할 식별자 정보를 담고 있는 객체
- Hoisting
- 코드 실행 전에 자바스크립트 엔진이 컨텍스트에서 변수명을 수집하는 것
- outerEnvironmentReference
- 현재 컨텍스트가 호출된 시점의 컨텍스트를 담고 있는 레퍼런스를 담고 있는 객체
- 스코프 (scope)
- 식별자에 대한 유효 범위
- 함수 스코프(function scope)
- ES5 에서 함수에 의해서만 스코프가 생김: var
- 블록 스코프(block scope)
- ES6 에서 블록에 의해서도 스코프가 생김: let, const, class, Strict mode
- 스코프 체이닝(scope chaining)
- 현재 scope, 컨텍스트에서 식별자를 찾을 수 없는 경우 outerEnvironmentReference를 통해 상위 스코프, 컨텍스트에서 식별자를 찾아 가는 방식
- 변수 은닉화(variable shadowing)
- 스코프 체이닝의 특성을 이용해, 자식 컨텍스트에 전역 변수 명과 동일한 변수를 선언함으로써 전역 변수 접근을 막는 방식
- 함수 선언식
- 실행 컨텍스트가 수집될 때 함수 그 자체가 호이스팅 됨
- 지양하자
- 함수 표현식
- 실행 컨텍스트가 수집될 때 선언부만 호이스팅 되고, 할당 시점에 함수가 할당됨
06. 궁금한것
- VariableEnvironment 은 어디에 사용되는가?
- es5 → var에 대한 정보, es6 → let, const ...
- 함수 선언식과 표현식을 같이 쓰는 경우에는 호이스팅이 어떻게 되는가? sum 변수는 선언/할당, new_sum은 선언부만 hoisting 됨?
var new_sum = function sum(){}