Knowledge Map

ES5 에서의 실행 컨텍스트 본문

WEB/JAVASCRIPT

ES5 에서의 실행 컨텍스트

2017. 7. 31. 17:44

출처 : https://es5.github.io/#x10


10. 실행 가능한 코드와 실행 컨텍스트


ECMAScript실행 가능한 코드에는 3가지 유형이 있다.


- 전역 코드는 ECMAScript 프로그램으로 취급되는 소스 텍스트이다. 특정 프로그램의 전역 코드는 FunctionBody의 일부로 파싱되는 소스 텍스트를 포함하지 않는다.


- Eval code는 빌트인 eval 함수로부터 공급되는 소스 텍스트이다. 보다 정확하게, 빌트인 eval 함수에 매개 변수가 string 이면 ECMAScript 프로그램으로 처리된다. eval의 특정 호출에 대한 eval 코드는 해당 프로그램의 전역 코드 부분이다.


- 함수 코드는 FunctionBody 부분으로 파싱되는 소스 텍스트이다. 특정 FunctionBody의 함수코드는 중첩된 FunctionBody 부분을 파싱한 소스 텍스트를 포함하지 않는다. 함수코드는 또한 빌트인 Function 객체를 생성자로서 사용할 때 제공되는 소스 텍스트를 나타내기도 한다. 좀더 정확하게, Function 생성자에 제공된 마지막 매개변수는 String으로 변환되어 FunctionBody로 처리된다. Function 생성자에 둘 이상의 매개 변수가 제공되면 마지막 매개 변수를 제외한 모든 매개 변수가 문자열로 변환되고 함께 연결되며 쉼표로 구분된다. 그 결과로 만들어진 문자열은 마지막 매개 변수에 의해 정의된 FunctionBody에 대한 FormalParameterList로 해석된다. 함수의 특정 인스턴스화를 위한 함수 코드는 중첩된 FunctionBody의 일부로 파싱된 소스텍스트를 포함하지 않는다.




10.2 Lexical Environment


Lexical Environment은 ECMAScript 코드의 렉시컬 중첩 구조를 기반으로 하는 함수와 특정한 변수들에 대한 식별자를 정의하는 specification 타입이다.


Lexical Environment은 환경 레코드와 (가능하다면)외부 Lexical Environment에 대한 null 참조로 구성되어 있다. 대개 Lexical Environment은 FunctionDeclaration, WithStatement, TryStatement의 Catch 절과 같은 몇가지 특정한 구문 구조와 연관되어 있다. 그리고 새로운 Lexical Environment은 이러한 코드들이 평가될 때마다 만들어진다.


환경 레코드는 관련 Lexical Environment의 스코프 안에서 만들어진 식별자 바인딩들을 기록한다.


외부 환경 참조는 Lexical Environment 값들이 논리적 중첩을 모델링 하는데 사용된다.

(내부) Lexical Environment의 외부 참조는 논리적으로 내부 Lexical Environment을 둘러싼 Lexical Environment에 대한 참조이다. 물론 외부 Lexical Environment은 고유의 외부 Lexical Environment을 가질 수 있다. Lexical Environment은 여러 내부 Lexical Environment에 대한 외부 환경으로 사용될 수 있다. 예를 들어 FunctionDeclaration에 두개의 중첩된 FunctionDeclaration이 포함되면 중첩된 각 함수의 Lexical Environment은 주변 함수의 현재 실행에 대한 Lexical Environment을 외부 Lexical Environment으로 가질수 있다.


Lexical Environment 및 호나경 레코드의 값들은 순수하게 specification 메커니즘이며 ECMAScript 구현의 특정 산출물과 일치할 필요는 없다. ECMAScript 프로그램이 이렇나 값에 직접 액세스하거나 조작하는 것은 불가능하다.




10.2.1 환경 레코드


이 es5 명세에서는 선언적 환경 레코드 declarative environment records, 객체 환경 레코드 object environment records 라는 2가지 종류의 환경 레코드 값이 있다. 선언적 환경 레코드는 ECMAScript 언어 구문 앨리먼트의 효과를 정의하는데 사용되는데, 그 언어 구문 앨리먼트들이란, FunctionDeclarations, VariableDeclarations, Catch절이 있다. 이들은 식별자 바인딩을 ECMAScript 언어 값과 직접 연관 시킨다.


specificiation 목적을 위해 환경 레코드의 값은 환경레코드라는 간단한 객체 지향 계층 구조안에 존재하는 것으로 생각할수 있다. 환경 레코드는 선언적 환경 레코드와 객체환경 레코드라는 2개의 구체적인 서브클래스들을 가지고 있는 추상적인 클래스이다.


이 추상 클래스는 추상 스펙 메소드를 가지고 있는데, 이들 추상 메소드들은 구체적인 서브클래스 각각을 위한 별개의 구체적인 알고리즘을 가지고 있다. 



환경 레코드의 추상 메소드



HasBinding(N)

환경 레코드가 식별자에 대해 바인딩을 가지고 있는지에 대해 정의한다. 가지고 있으면 true, 아니면 false. string 값인 N은 식별자의 텍스트이다.


CreateMutableBinding(N, D)

환경 레코드안에서 변경가능한 새로운 바인딩을 만든다.string 값인 N은 바운드 이름에 대한 텍스트이다. 만약 옵션 boolean 인자 D가 true라면 이후에 삭제될 수 있다.


SetMutableBinding(N, V, S)

환경 레코드에 이미 존재하는 mutable 바인딩의 값을 설명한다. String 값 N은 바운드 이름에 대한 텍스트이다. V는 그 바인딩에 대한 값이며 어떠한 ECMAScript 언어 타입의 값이 될수 있다. S는 boolean 플래그로 만약 S가 true 이고 바인딩을 설정할수 없다면 TypeError 예외를 발생한다. S는 엄격 모드 참조를 식별하는데 사용된다.


GetBindingValue(N, S)

환경 레코드에서 이미 존재하는 바인딩의 값을 반환한다. string 값인 N은 바운드 이름이며 S는 엄격 모드 참조를 식별하는데 사용된다. 만약 S가 true이고 바인딩이 존재하지 않거나 초기화가 되지 않은 경우 ReferenceError 예외가 발생한다.


DeleteBinding(N)

환경 레코드에서 바인딩을 삭제한다. string 값인 N은 바운드 이름이며 만약 N의 바인딩이 존재한다면 바인딩을 삭제하고 true 반환한다. 만약 바인딩이 존재하지만 삭제할수 없을 경우에는 삭제 하지 못하고 false가 반환하며 아예 존재하지 않는 다면 true를 반환한다.


ImplicitThisValue()

함수 객체 호출시 this 값으로 사용할 값을 반환한다. 

Returns the value to use as the this value on calls to function objects that are obtained as binding values from this environment record.




10.2.1.1 선언적 환경 레코드


각각의 선언적 환경 레코드는 ECMAScript 프로그램 스코프와 연관되어 있다. 이 때의 스코프는 변수와 함수 선언을 포함하는데, 같이 포함될수도 있고 따로 포함할수도 있다. 선언적 환경 레코드는 해당 스코프안에 포함된 선언들에 의해 정의된 식별자 집합을 바인딩한다.


모든 환경 레코드가 지원하는 변경 가능한 바인딩 외에도 선언적 환경 레코드는 immutable 바인딩을 제공한다. immutable 바인딩은 식별자와 값사이의 연관이 한번 확립되면 변경되지 않는 바인딩이다. immutable 바인딩의 생성과 초기화는 별개의 단계이다. 그래서 초기화된 상태 또는 초기화되지 않는 상태의 바인딩이 존재할 수 있다. 선언적 환경 레코드는 환경 레코드 추상 스펙 메소드 외에도 CreateImmutableBinding(N), InitializeImmutableBinding(N, V) 라는 메소드를 지원한다.


CreateImmutableBinding(N) 는 새로운 초기화되지 않은 immutable binding을 환경 레코드 안에 만든다. N은 바운드 네임 텍스트이다.


InitializeImmutableBinding(N, V) 는 이미 존재하지만 초기화되지 않은 immutable binding의 값을 설정한다. N은 바운드 네임 텍스트(string)이며, V는 바인딩에 대한 값이고 그 값은 ECMAScript 언어 타입중 하나의 값이다.



10.2.1.2 객체 환경 레코드


각각의 객체 환경 레코드는 binding object로 불리는 객체와 연관이 있다. 객체 환경 레코드는 해당  binding object의 프로퍼티 이름과 직접적으로 대응되는 식별자이름들의 집합을 바인드한다. 식별자 이름이 아닌 프로퍼티 이름은 바운드 식별자 집합에 포함되지 않는다. 자신의 속성과 상속된 속성은 모두 [[Enumerable]] 특성 설정에 관계 없이 집합에 포함된다. 특성은 객체에서 동적으로 추가되거나 삭제될 수 있기 때문에 객체 환경 레코드에 의해 바인드된 식별자들의 집합은 프로퍼티들을 추가하거나 삭제하는 어떠한 조작의 부작용으로 잠재적으로 변경할수 있다. 


그러한 부작용의 결과로 생성된 바인딩은 해당 등록 정보의 Writable 속성 값이 false인 경우에도 변경 가능한 바인딩으로 간주된다. 객체 환경 레코드에는 변경할 수 없는 바인딩이 없다.


객체 환경 레코드는  binding object를 함수 호출에 사용할 암시적 this 값으로 제공하도록 구성될 수 있다. 이기능은 With문 유도 바인딩의 동작을 지정하는데 사용된다. 이 능력은 각각의 객체환경 레코드와 연관된 provideThis boolean 값에 의해 제어된다. 기본적으로 provideThis 값은 false이다.



10.3 실행 컨텍스트


컨트롤이 ECMAScript 실행 코드로 이동되면 컨트롤은 실행 컨텍스트로 들어간다. 액티브 실행 컨텍스트는 논리적으로 스택을 형성한다. 이 논리 스택의 최상위 실행 컨텍스트는 실행 중인 실행 컨텍스트이다. 


현재의 실행중인 실행 컨텍스트와 연관된 실행 코드 에서 해당 실행 컨텍스트와 연관되어 있지 않는 실행코드로 컨트롤이 이동할 때 마다 새로운 실행 컨텍스트가 만들어진다. 새로 생성된 실행 컨텍스트는 스택에 푸시되고 실행중인 실행 컨텍스트가 된다.


실행 컨텍스트에는 그것과 연관된 코드의 실행 진행상황를 추적하는데 필요한 모든 상태(state)가 포함된다. 또한 각 실행 컨텍스트는 Lexical Environment, Variable Environment, ThisBinding 이라는 상태 컴포넌트들을 가지고 있다.


Lexical Environment : 실행 컨텍스트 내에서 코드로 작성된 식별자 참조를 확인하는데 사용된다.


Variable Environment : 환경 컨텍스트내에서 FunctionDeclarations와 VariableStatement에 의해 생성된 바인딩을 보유하는 환경 레코드인 Lexical Environment


ThisBinding : 실행 컨텍스트와 연관된 ECMAScript 코드내에서 'this' 키워드와 연관되어 있는 값



실행 컨텍스트에서의 Lexical Environment과 Variable Environment 컴포넌트는 항상 Lexical Environment이다. 실행 컨텍스트가 생성되면 Lexical Environment과 Variable Environment 컴포넌트의 초기 값은 동일하다. 실행 컨텍스트내에서 코드가 실행하는 동안, Lexical Environment 컴포넌트의 값은 변경될 수 있는데 반면 Variable Environment 컴포넌트는 결코 변경되지 않는다.


이 스펙에서는 대부분의 상황에서 실행중인 실행 컨텍스트만이 알고리즘에 의해 직접 조작된다. 따라서  용어 'Lexical Environment', 'Variable Environment' 및 'ThisBinding'이 자격없이 사용되면 실행중인 실행 컨텍스트의 해당 컴포넌트를 참조한다.


실행 컨텍스트는 순전히 specification 메커니즘이며 ECMAScript 구현의 특정 산출물과 일치할 필요는 없다. ECMAScript 프로그램이 실행 컨텍스트에 액세스 하는 것은 불가능하다.



10.3.1 Identifier Resolution


Identifier Resolution은 실행중인 실행 컨텍스트의 LexicalEnvironment를 사용하여 식별자의 바인딩을 결정하는 프로세스이다.

ECMAScript 코드를 실행하는 동안,  syntactic production PrimaryExpression : Identifier는 다음 알고리즘을 사용하여 평가된다.


1, env는 실행중인 실행컨텍스트의 LexicalEnvironment라고 하자

2. 만약 평가된 syntactic production 에 엄격 모드 코드가 포함되어 있다면 strict는 true 아니면 false 이다.

3. env, Identifier, strict를 인자로 넘기는 GetIdentifierRefence 함수 호출의 결과를 반환한다. 


식별자를 평가한 결과는 항상 Reference 타입의 값이며 참조된 이름의 컴포넌트는 식별자 문자열과 동일하다.


10.4 Establishing an Execution Context


전역 코드 또는 eval 함수를 이용한 코드의 평가는 새로운 실행 컨텍스트를 생성하고 들어가게 된다. ECMAScript 코드 함수의 모든 호출 또한 그러하다. 심지어 재귀 호출을 조차도 마찬가지이다. 모든 return은 실행컨텍스트를 종료한다. thrown exception 또한 하나 이상의 실행 컨텍스트를 종료 할 수 있다.


컨트롤이 실행 컨텍스트에 진입할때, 실행 컨텍스트의 ThisBinding이 설정되고, VariableEnvironment와 초기 LexicalEnvironment가 정의된다. 그리고 선언 바인딩 인스턴스화가 수행된다. 이러한 동작이 발생하는 정확한 방식은 입력되는 코드의 타입에 따라 다르다.


10.4.1 Entering Global Code

컨트롤이 전역코드를 위한 실행 컨텍스트로 진입할때 일어나는 단계

1. 전역 코드를 사용해서 실행 컨텍스트를 초기화한다.

2. 전역 코드를 이용해서 선언 바인딩 인스턴스화를 행한다.


10.4.1.1 Global Execution Context 초기화


1. 전역 환경의 VariableEnvironment를 설정한다.

2. 전역 환경의 LexicalEnvironment를 설정한다.

3. 전역객체의 ThisBinding을 설정한다.


10.4.3 Entering Function Code

컨트롤이 함수 객체 F안에 있는 함수 코드에 대한 실행 컨텍스트로 진입할때 다음의 단계가 일어난다. 호출자가 thisArg와 argumentsList를 제공한다.


1. 함수코드가 만약 strict 코드라면 ThisBinding을 thisArg로 설정한다.

2. 아니고 만약 thisArg가 null이거나 undefined라면 ThisBinding을 전역 객체로 설정한다.

3. 아니고 만약 thisArg의 타입이 Object가 아니라면 ThisBinding를 ToObject(thisArg)로 설정한다.

4. 아니면 ThisBinding을 thisArg로 한다.

5. localEnv를 NewDeclarativeEnvironment 호출의 결과라고 하자. 이것은 인자로서 F의 [[Scope]] 내부 프로퍼티의 값을 받는다.

6. Set the LexicalEnvironment to localEnv.

7. Set the VariableEnvironment to localEnv.

8. code를 F의 [[Code]] 내부 프로퍼티의 값이라고 하자

9. 함수 코드의 code 와 argumentList를 이용해 선언 바인딩 인스턴스화를 행한다.





10.5 Declaration Binding Instantiation 선언 바인딩 인스턴스화


모든 실행 컨텍스트에는 연관된 VariableEnvironment가 있다. 실행 컨텍스트에서 평가된 ECMAScript 코드에서 선언된 변수와 함수는 해당 VariableEnvironment의 환경 레코드에 바인딩으로 추가된다. 함수 코드의 경우 매개변수가 해당 환경 레코드에 대한 바인딩으로 추가된다.


Which Environment Record is used to bind a declaration and its kind depends upon the type of ECMAScript code executed by the execution context, but the remainder of the behaviour is generic. 



실행 컨텍스트를 입력 할 때 호출자가 제공 한 코드를 사용하여 VariableEnvironment에 바인딩이 만들어지고 함수 코드 인 경우 인수 args가 나타납니다.






나중에 시간나면 

http://dmitrysoshnikov.com/ecmascript/es5-chapter-3-2-lexical-environments-ecmascript-implementation/#variable-environment

https://stackoverflow.com/questions/12599965/lexical-environment-and-function-scope

읽고 보완할것..

'WEB > JAVASCRIPT' 카테고리의 다른 글

2차원 행렬 클래스  (0) 2017.09.08
Dispatch  (0) 2017.08.06
javascript API Geolocation  (0) 2017.04.25
자릿수 콤마 넣기  (0) 2017.04.23
window.onload  (0) 2017.03.22
Comments