var x = 10;
function foo() {
var y = 20;
function bar() {
alert(x + y);
}
return bar;
}
foo()(); // 30
作用域链与一个执行上下文相关,变量对象的链用于在标识符解析中变量查找。
activeExecutionContext = {
VO: {...}, // or AO
this: thisValue,
Scope: [ // Scope chain
// 所有变量对象的列表
// for identifiers lookup
]
};
Scope = AO + [[Scope]]
var x = 10;
function foo() {
var y = 20;
alert(x + y);
}
foo(); // 30
fooContext.AO = {
y: undefined // undefined – 进入上下文的时候是20 – at activation
};
foo.[[Scope]] = [
globalContext.VO // === Global
];
Scope = AO|VO + [[Scope]]
Scope = [AO].concat([[Scope]]);
var x = 10;
function foo() {
var y = 20;
function bar() {
var z = 30;
alert(x + y + z);
}
bar();
}
foo(); // 60
globalContext.VO === Global = {
x: 10
foo: <reference to function>
};
foo.[[Scope]] = [
globalContext.VO
];
fooContext.AO = {
y: 20,
bar: <reference to function>
};
fooContext.Scope = fooContext.AO + foo.[[Scope]] // i.e.:
fooContext.Scope = [
fooContext.AO,
globalContext.VO
];
bar.[[Scope]] = [
fooContext.AO,
globalContext.VO
];
barContext.AO = {
z: 30
};
barContext.Scope = barContext.AO + bar.[[Scope]] // i.e.:
barContext.Scope = [
barContext.AO,
fooContext.AO,
globalContext.VO
];
- "x"
-- barContext.AO // not found
-- fooContext.AO // not found
-- globalContext.VO // found - 10
- "y"
-- barContext.AO // not found
-- fooContext.AO // found - 20
- "z"
-- barContext.AO // found - 30
var x = 10;
function foo() {
alert(x);
}
(function () {
var x = 20;
foo(); // 10, but not 20
})();
var x = 10;
function foo() {
var y = 20;
function barFD() { // 函数声明
alert(x);
alert(y);
}
var barFE = function () { // 函数表达式
alert(x);
alert(y);
};
var barFn = Function('alert(x); alert(y);');
barFD(); // 10, 20
barFE(); // 10, 20
barFn(); // 10, "y" is not defined
}
foo();
function foo() {
alert(x);
}
Object.prototype.x = 10;
foo(); // 10
function foo() {
var x = 20;
function bar() {
alert(x);
}
bar();
}
Object.prototype.x = 10;
foo(); // 20
globalContext.Scope = [
Global
];
evalContext.Scope === callingContext.Scope;
Scope = withObject|catchObject + AO|VO + [[Scope]]
var foo = {x: 10, y: 20};
with (foo) {
alert(x); // 10
alert(y); // 20
}
Scope = foo + AO|VO + [[Scope]]
var x = 10, y = 10;
with ({x: 20}) {
var x = 30, y = 30;
alert(x); // 30
alert(y); // 30
}
alert(x); // 10
alert(y); // 30
try {
...
} catch (ex) {
alert(ex);
}
var catchObject = {
ex: <exception object>
};
Scope = catchObject + AO|VO + [[Scope]]