JS
var data = [];
for (var k = 0; k < 3; k++) {
debugger;
console.log("inner: "+k);
data[k] = function () {
debugger;
console.log("func: "+k);
};
}
console.log("outer: "+k);
data[0](); // 3, 而不是0
data[1](); // 3, 而不是1
data[2](); // 3, 而不是2
15:06:59.381 VM66691:5 inner: 0
15:07:00.125 VM66691:5 inner: 1
15:07:01.292 VM66691:5 inner: 2
15:07:01.292 VM66691:11 outer: 3
15:07:01.492 VM66691:8 func: 3
15:07:01.700 VM66691:8 func: 3
15:07:01.905 VM66691:8 func: 3
15:07:01.929 undefined
eval()和Function构造不同
eval()可以干扰作用域链.
而Function()更安分守己些。
不管你在哪里执行 Function(),它只看到全局作用域。所以其能很好的避免本地变量污染。在下面这个例子中,eval()可以访问和修改它外部作用域中的变量,这是 Function做不来的(注意到使用Function和new Function是相同的)。
(function () {
var local = 1;
eval("local = 3; console.log(local)"); // logs "3"
console.log(local); // logs "3"
}());
(function () {
var local = 1;
Function("console.log(typeof local);")(); // logs undefined
}());
ECMAScript只使用静态(词法)作用域(而诸如Perl这样的语言,既可以使用静态作用域也可以使用动态作用域进行变量声明)。
var x = 10;
function foo() {
alert(x);//保持 x = 10
}
(function (funArg) {
var x = 20;
// 变量"x"在(lexical)上下文中静态保存的,在该函数创建的时候就保存了
funArg(); // 10, 而不是20
})(foo);
技术上说,创建该函数的父级上下文的数据是保存在函数的内部属性 [[Scope]]中的
所有对象都引用一个[[Scope]]
这里还要注意的是:在ECMAScript中,同一个父上下文中创建的闭包是共用一个[[Scope]]属性的。也就是说,某个闭包对其中[[Scope]]的变量做修改会影响到其他闭包对其变量的读取:
var firstClosure;
var secondClosure;
function foo() {
var x = 1;
firstClosure = function () { return ++x; };
secondClosure = function () { return --x; };
x = 2; // 影响 AO["x"], 在2个闭包公有的[[Scope]]中
alert(firstClosure()); // 3, 通过第一个闭包的[[Scope]]
}
foo();
alert(firstClosure()); // 4
alert(secondClosure()); // 3