function
키워드를 만나면 Function Object를 생성하고 각종 정보를 설정한다.엔진이 function
키워드를 만나 Function Object를 생성하는 과정을 살펴보면, 실행 컨텍스트의 외부 렉시컬 참조가 어떻게 설정되는지 알 수 있다.
new
키워드를 이용해서 함수 객체를 만들 수 있다.var test = function()
이라는 문장을 만나면(function 키워드를 만나면), built-in Function Object의 prototype에 연결된 메소드로 Function Object를 생성한다. new
키워드로 만든 Function 인스턴스와는 차이가 있다.test()
라는 코드를 만났을 땐, 식별자 해결을 통해 test 변수가 Function Object라는 것을 알게 되면 호출을 진행하게 된다.실행 컨텍스트 : {
렉시컬 환경 : {
선언적 환경 레코드 : {
함수명 : Function Object,
변수명 : 값,
}
}
}
함수명 : Function Object
의 형태로 변경해준다. 따라서 우리가 함수명()
형태로 함수를 호출하면, 엔진은 Scope를 뒤져가며 함수명으로 식별자 해결을 진행한다. 식별자 해결을 하여 함수 이름이 가진 value가 Function Object가 맞다면 비로소 호출을 진행한다. function test(){...}
키워드를 사용해서 함수를 선언우리는 Lexical Environment의 "외부 렉시컬 참조를 통해" 함수 바로 바깥에 있는 변수에 접근할 수 있다. 지금 비어진 Function Object에 함수가 속한 Scope를 설정해둔다. 이후 함수가 호출되는 시점에 엔진은 Function Object의 내용물을 기반으로 실행 컨텍스트의 "외부 렉시컬 참조"가 설정한다.
[[Scope]]
의 value로 저장한다. 내부 프로퍼티란?
내부 프로퍼티란 일반 프로퍼티와 달리, 엔진이 내부적인 처리를 위해 사용하는 프로퍼티로 개발자가 접근할 수 없는 프로퍼티다. 내부 프로퍼티는
[[Scope]] : { }
와 같이 중괄호 두개로 표현된다.
built-in Object들이 모두 가지고 있는 내부 프로퍼티를 "공통 프로퍼티"라고 하며, built-in Object의 종류마다 다른 처리를 위해 달리 들고 있는 프로퍼티를 "선택적 프로퍼티"라고 한다.
[[Scope]] : {...환경}
의 형태로 저장되어 외부 렉시컬 참조의 설정 때 쓰인다.[[Code]]
에 함수 내부의 코드들을 저장해둔다. 즉, function 키워드가 존재하는 컨텍스트의 선언적 환경 레코드에 함수명 : Function Object
의 형태로 저장되며, 현재의 Scope는 Function Object에 [[Scope]] : {...환경}
의 형태로 저장되어 외부 렉시컬 참조의 설정 때 쓰인다.
Function Object가 생성되면서, 내부 프로퍼티 [[Scope]]
에 타겟 함수의 Scope를 설정해둔다. 이렇게 설정된 Scope는 절대 변경되지 않는다. 따라서 자바스크립트는 "정적 Scope", "정적 환경"이라고 부를 수 있다.
우리는
apply()
와 같은 메소드를 사용해서 This 바인딩 컴포넌트가 참조하는 대상을 동적으로 변경할 수 있었다. 이처럼 외부 렉시컬 참조가 가지는 Scope를 동적으로도 변경할 수"도" 있다.
with
문,eval()
등으로 Scope를 동적으로 변경 가능하다.
사실 실행 컨텍스트의 초기화 단계는 더 세분화된다.
var a = 123
; 과 var b = function(){}
는 모두 표현식이다.(변수에 할당하는 형태는 모두 표현식이다.)따라서 함수 선언문들은 초기화 단계에서 Function Object가 생성되면서 Scope가 결정되지만, 함수 표현식의 경우 함수명 : Undefined
로 환경에 설정되어 있다가 코드가 실행되는 단계에서 Function Object가 생성되어 Scope가 결정된다.
function book() {
var title = "타이틀";
function getBook() {
return title;
}
var readBook = function () {};
getBook();
}
book();
[[Scope]]
에 넣어주는 단계function getBook(){};
var title = undefined;
var readBook = undefined;
var title = "타이틀";
var readBook = function(){};
getBook();