JS 엔진은 함수를 실행하기 위해, 함수 실행에 필요한 모든 변수나 함수등을 실행 컨텍스트라는 덩어리에 묶는다. 이번 포스트에서 실제 그 덩어리는 어떻게 생겼는지를 알아보겠습니다.
실행컨텍스트_EC : {
렉시컬환경컴포넌트_LEC : { },
변수환경컴포넌트_VEC : { },
This바인딩컴포넌트_TBC : { }
}
이제 3개의 컴포넌트에 대해 차례차례 알아보자
LEC의 내부 구조는 다음과 같다.
렉시컬 환경 컴포넌트 : {
환경 레코드 : {
선언적 환경 레코드 : { },
오브젝트 환경 레코드 : { },
},
외부 렉시컬 환경 참조 : {}
}
변수명 : undefined
형태로 저장되며, 함수선언문은 함수명 : undefined
형태로 저장된다. 초기화 단계가 끝나고 코드가 실행되면서 Value 값들이 적용된다.function
키워드가 속한 Scope의 변수나 함수들을 외부 렉시컬 환경 참조에 저장한다. 환경 레코드는 선언적 환경 레코드와 오브젝트 환경 레코드로 나뉜다. 모든 실행 컨텍스트는 이와 같은 동일한 구조를 갖지만, 동적 환경은 오브젝트 환경 레코드를 사용하고 정적 환경은 선언적 환경 레코드를 사용한다.
function
, 일반 변수, catch
문 내부 변수들은 선언적 환경 레코드에 저장된다. 여기에 저장되는 환경들은 정적으로 설정된다. 즉 한 번 설정되면, 값은 변할지라도 key값은 변하지 않는다.
실행컨텍스트 : {
글로벌환경 : {
환경레코드 : { 오브젝트환경레코드 : 글로벌 오브젝트 },
외부렉시컬환경참조 : null
}
}
JS 엔진은 global object의 생성과 with
문을 만나면 동적 환경(즉, 환경이 런타임때마다 변하는)을 생성한다. 오브젝트 환경 레코드는 동적으로 처리되는 환경이 저장되므로, 오브젝트 환경 레코드만 사용하면 된다. 글로벌 오브젝트는 어디에도 속하지 않으므로 외부 렉시컬 환경 참조값은 NULL이다.
var value = 100
function getMyValue(){
var value = 200
var temp = 300
return value
}
getMyValue()
getMyValue 실행 컨텍스트 : {
렉시컬 환경 컴포넌트 : {
환경레코드 : {
선언적 환경 레코드 : {
value : 200,
temp : 300
},
오브젝트 환경 레코드 : { }
},
외부렉시컬환경참조 : {
value : 100
}
}
}
getMyValue : Function Object
형태로 저장한다.this
는 Javascript의 키워드다. obj.aa() 형태로 호출한 함수(메소드) aa 에서는 this로 인스턴스(오브젝트)를 참조할 수 있다. 메소드가 호출될 때 객체가 실행 컨텍스트의 This 바인딩 컴포넌트에 바인딩된다. 따라서, 함수 내부에서 this 키워드로 객체를 참조하여 obj의 변수나 함수를 사용할 수 있다.
this
키워드를 사용하여 함수를 호출한 오브젝트에 접근할 수 있도록, 함수의 실행 컨텍스트안에 해당 오브젝트를 참조하는 공간을 둔 것이 TBC다.this는 동적으로 결정된다.
call()
,apply()
,bind()
등의 메소드를 통해 this로 참조할 객체를 변경할 수 있으며, this로 참조할 객체는 호출 시점에 결정된다고 알고 있을 것이다. 즉 동적으로 결정된다. 이것이 가능한 이유는 TBC는 동적으로 바인딩되기 때문이다.
var obj = {value : 1000}
function getValue(){
var something = 999
return this.value
}
getValue()
//=> this가 global로 binding 됨
//=> undefined 출력
getValue.call(obj)
//=> this 바인딩 컴포넌트에 obj의 scope가 들어온다.
//=> 1000 출력
getValue.call(obj)일 때 실행컨텍스트
getValue 컨텍스트 : {
환경 레코드 : {
선언적 환경 레코드 : { something : 999 },
외부 렉시컬 환경 참조 : { obj : Object }
},
오브젝트 환경 레코드 : { },
this바인딩 컴포넌트 : { value : 1000 }
}
외부 렉시컬 환경 참조를 설정 과정을 이해하기 위해, JS 엔진이 Function Object를 처리하는 방식에 대해 포스팅 하겠습니다.