lexical environment in ecma 262 5
TRANSCRIPT
By 김훈민NHN Technology Services Corp.
Front-End Development Team
http://huns.me
Lexical Environment in ECMA-262 Edition 5.1
ECMA-262 Edition 5, 2009ECMA-262 Edition 3 탄생 이후 10 년
JSON
Function
ObjectArrays
use strict
Date
New Features in ECMA-262 Edition 5
1 more thing.
I will note that there are some real improvements in ES5, in particular to
Chapter 10 which now uses declarative
binding environments. ES1-3's abuse of objects for scopes (again I'm to blame for doing so in JS in 1995, economizing on objects needed to implement the language in a big hurry)
was a bug, not a feature.
https://mail.mozilla.org/pipermail/es-discuss/2010-April/010915.html
Before ECMA 262-5…?
Variable Object
Chapter 10.
Execution Context ECMAScript 코드를 실행하는 환경
Execution Context
<script> var sayHello = "Hello";
function person(){ var first = 'David';
function getFirstName(){ eval("first = 'Steven'"); return first; }
alert(sayHello + getFirstName()); } person(); </script>
Execution Context
Execution Context Stack
Execution Context
Execution Context
Execution Context
Execution Context
Executable Code
<script> var sayHello = "Hello";
function person(){ var first = 'David';
function getFirstName(){ eval("first = 'Steven'"); return first; }
alert(sayHello + getFirstName()); } person(); </script>
FunctionCode
Global Code
EvalCode
Evaluating
Initializing execution context
Initializing execution context
Initializing execution context
Pseudo code
ExecutionContext = {
LexicalEnvironment : [Lexical Environment], VariableEnvironment : [Lexical Environment], ThisBinding : [object]
}
* […] 은 Value Type
Lexical Environment자원을 어디에서 찾을 것인가
Components of Lexical Environment
lexical environment = {
environment record : -, outer environment reference : - }
지역 식별자 덩어리유효범위 내의 식별자를 바인딩
중첩 유효범위를 가질 수 있는 환경에서 상위 lexical environment 를 참조
2 type of environment record
Declarative vs
Object
DeclarativeEnvironmentRecord : {
x : 10, y : 20, result : 30
}
ObjectEnvironmentRecord : {
bindObject : globalObject
}
Establishing an Execution Context
실행 콘텍스트 초기화thisBinding, Hoisting
Global Code
{ LexicalEnvironment : globalEnv, VariableEnvironment : globalEnv, ThisBinding : window}
Global Execution Context
ObjectEnvironmentRecord : { bindingObject : window},OuterEnvironmentReferece : null,
globalEnv
function sum(x, y){ var result = x + y; var barr = function(){ console.log("barr"); }
function printResult(){ console.log(result); } return printResult; }
sum(10, 20);
Global Execution Context
sum’sExecution Context
Function Code
thisBinding
sunFunctionEC.thisBinding = null;
function sum(x, y){ var result = x + y; var barr = function(){ console.log("barr"); }
function printResult(){ console.log(result); } return printResult; }
sum(10, 20);
{
ThisBinding : null,
}
sumFunctionEC
thisBinding
sunFunctionEC.thisBinding = null;
function sum(x, y){ var result = x + y; var barr = function(){ console.log("barr"); }
function printResult(){ console.log(result); } return printResult; }
sum(10, 20);
{
ThisBinding : null,
}
sumFunctionEC
ThisBinding 이 null, undefined 인 경우this = global
“use strict” 모드에서는 this = null
thisBinding on Function
sunFunctionEC.ThisBinding = foo;foo.sum(10, 20);
{
ThisBinding : foo,
}
sumFunctionEC
{ ThisBinding : null, LexicalEnv : -}
sumFunctionEC
EnvironmentRecord : {}
localEnv
localEnv
Creating local lexical environment
Declaration Binding Instantiation실행 콘텍스트 바인딩 초기화
function sum(x, y){
console.log(barr);
var result = x + y; var barr = function(){ console.log("barr"); }
function printResult(){ console.log(result); } return printResult; }
sum(10, 20);
{ ThisBinding : null, LexicalEnv : localEnv}
sumFunctionEC
EnvironmentRecord : {
}
x : 10,y : 20,
localEnv
Declaration Binding Instantiation
EnvironmentRecord : { x : 10, y : 20,
}
function sum(x, y){
console.log(barr);
var result = x + y; var barr = function(){ console.log("barr"); }
function printResult(){ console.log(result); } return printResult; }
sum(10, 20);
printResult : Function Reference
Hoisting
{ ThisBinding : null, LexicalEnv : localEnv}
sumFunctionEC
localEnv
Declaration Binding Instantiation
function sum(x, y){
console.log(barr);
var result = x + y; var barr = function(){ console.log("barr"); }
function printResult(){ console.log(result); } return printResult; }
sum(10, 20);
EnvironmentRecord : { x : 10, y : 20, printResult : Function Reference,
}
arguments : Arguments Object
{ ThisBinding : null, LexicalEnv : localEnv}
sumFunctionEC
localEnv
Declaration Binding Instantiation
EnvironmentRecord : { x : 10, y : 20, printResult : Function Reference
}
function sum(x, y){
console.log(barr);
var result = x + y; var barr = function(){ console.log("barr"); }
function printResult(){ console.log(result); } return printResult; }
sum(10, 20);
result : undefined,barr : undefined
Hoisting
{ ThisBinding : null, LexicalEnv : localEnv}
sumFunctionEC
localEnv
Declaration Binding Instantiation
EnvironmentRecord : { x : 10, y : 20, printResult : Function Reference, result : undefined, barr : undefined
}
function sum(x, y){
console.log(barr);
var result = x + y; var barr = function(){ console.log("barr"); }
function printResult(){ console.log(result); } return printResult; }
sum(10, 20);
{ ThisBinding : null, LexicalEnv : localEnv}
sumFunctionEC
localEnv
Declaration Binding Instantiation
function sum(x, y){
console.log(barr);
var result = x + y; var barr = function(){ console.log("barr"); }
function foo(){ console.log("foo"); } return result; }
sum(10, 20); result : 30,barr : Function Reference
{ ThisBinding : null, LexicalEnv : localEnv}
sumFunctionEC
EnvironmentRecord : { x : 10, y : 20, foo : Function Reference result : undefined, barr : undefined
}
localEnv
Declaration Binding Instantiation
result : 30,barr : Function Reference
Identifier Resolution식별자와 묶여있는 값을 찾아가는 과정
스코프 체인의 원리
outer environment reference
The outer environment reference is used
to model the logical nesting of Lexical Environment values
var a = 10; (function foo() { var b = 20;
(function bar() { var c = 30; console.log( a + b + c );
})();
})();
Identifier Resolution #1
GlobalExecution Context
foo’sExecution Context
bar’sExecution Context
var a = 10; (function foo() { var b = 20;
(function bar() { var c = 30; console.log( a + b + c );
})();
})();
LexicalEnvironment : { EnvironmentRecord : { c : 30 } OuterEnvironmentReference : fooEC.LexicalEnvironment},
bar’s EC
LexicalEnvironment : { EnvironmentRecord : { b : 20 } OuterEnvironmentReference : globalEC.LexicalEnvironment},
foo’s EC
LexicalEnvironment : { EnvironmentRecord : { a : 10 } OuterEnvironmentReference : null},
Global EC
Identifier Resolution #1
var a = 10; (function foo() { var b = 20;
(function bar() { var c = 30; console.log( a + b + c );
})();
})();
LexicalEnvironment : { EnvironmentRecord : { c : 30 } OuterEnvironmentReference : fooEC.LexicalEnvironment},
barEC
LexicalEnvironment : { EnvironmentRecord : { b : 20 } OuterEnvironmentReference : globalEC.LexicalEnvironment},
fooEC
LexicalEnvironment : { EnvironmentRecord : { a : 10 } OuterEnvironmentReference : null},
globalEC
Identifier Resolution #2
Closure자유변수를 간직한 코드 블럭
A lexical environment that defines the environment in which a Function object is executed.
Function Object’sInternal property
[[Scope]]
function sum(x, y){ var result = x + y;
function printResult(){ console.log("foo:”+ result); } return printResult; }
var print = sum(10, 20);print();
LexicalEnvironment = { EnvironmentRecord : { x : 10, y : 20, result : undefined, printResult : function }, OuterEnvironmentReference : globalEC.lexicalEnvironment},
ThisBinding : null
sum’s EC
[[Scope]]:
printResult function
sumEC’s lexical environment
Creating Function Object
function sum(x, y){ var result = x + y;
function printResult(){ console.log("foo:”+ result); } return printResult; }
var print = sum(10, 20);print();
[[Scope]]:
printResult function
sumEC’s lexical environment
ThisBinding : null
sum’s EC
LexicalEnvironment = { EnvironmentRecord : { x : 10, y : 20, result : undefined, printResult : function }, OuterEnvironmentReference : globalEC.lexicalEnvironment},
Closure
function sum(x, y){ var result = x + y;
function printResult(){ console.log("foo:”+ result); } return printResult; }
var print = sum(10, 20);print();
[[Scope]]:
printResult function
sumEC’s lexical environment
LexicalEnvironment = { EnvironmentRecord : { x : 10, y : 20, result : undefined, printResult : function }, OuterEnvironmentReference : globalEC.lexicalEnvironment},
Closure
[[Scope]]: sumEC’s lexical environment
printResult function
Creating printResult’s EC
LexicalEnvironment = { EnvironmentRecord : { … }, OuterEnvironmentReference : sumEC’s lexical environment},ThisBinding : null
printResult’s ECfunction sum(x, y){ var result = x + y;
function printResult(){ console.log("foo:”+ result); } return printResult; }
var print = sum(10, 20);print();
VariableEnvironmentLexicalEnvironment 의 쌍둥이
Execution Context Pseudo code
ExecutionContext = {
LexicalEnvironment : [lexical environment],
VariableEnvironment : [lexical environment], ThisBinding : [object]
}
* […] 은 type
LexicalEnvironment and VariableEnvironment
components of an execution context
are always Lexical Environments
- 10.3 Execution Contexts in ECMA 262-5 -
VariableEnvironment = LexicalEnvironment
{ ThisBinding : null, LexicalEnv : globalEnv,
VariableEnv : null}
Global EC
EnvironmentRecord : { bindingObject : window},OuterEnviromentReferece : null
globalEnv
var foo = "abc";
with({ foo : "bar" }) {
function f() { console.log(foo); }
f(); }
GlobalEC.VariableEnv = GlobalEC.LexicalEnv;
globalEnv
The value of the VariableEnvironment component never changes while the value of the LexicalEnvironment component
may change during execution of code within an execution context.
- 10.3 Execution Contexts in ECMA 262-5 -
With Statement #1
{ ThisBinding : null, LexicalEnv : globalEnv, VariableEnv : globalEnv}
Global EC
EnvironmentRecord : { bindingObject : window},OuterEnviromentReferece : null
globalEnv
var foo = "abc";
with({ foo : "bar" }) {
function f() { console.log(foo); }
f(); }
ObjectEnvironmentRecord : { bindingObject : -},OuterEnviromentReferece :
newEnv{foo:bar}
newEnv,
GlobalEC.LexicalEnv
With Statement #2
{ ThisBinding : null, LexicalEnv : newEnv, VariableEnv : globalEnv}
Global EC
EnvironmentRecord : { bindingObject : window},OuterEnviromentReferece : null
globalEnv
var foo = "abc";
with({ foo : "bar" }) {
function f() { console.log(foo); }
f(); }
ObjectEnvironmentRecord : { bindingObject : { foo : bar }},OuterEnviromentReferece : GlobalEC.LexicalEnv
newEnv
With Statement #3
{ ThisBinding : null, LexicalEnv : newEnv, VariableEnv : globalEnv}
Global EC
EnvironmentRecord : { bindingObject : window},OuterEnviromentReferece : null
globalEnv
ObjectEnvironmentRecord : { bindingObject : { foo : bar }},OuterEnviromentReferece : null
newEnv
globalEnvwith 문이 끝나면
GlobalEC.LexicalEnv = GlobalEC.VariableEnv;
Reference
1. ECMAScript Language Specification 5.1 Edition2. ECMAScript 5 spec: LexicalEnvironment versus VariableEnvironment3. ECMA-262-5 in detail. Chapter 3.2 Lexical environments