闭包与变量
作用域链的这种配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。
下面这个例子可以清晰地说明这个问题。
javascript
function createFunctions() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function () {
return i;
};
}
return result;
}
这个函数会返回一个函数数组。表面上看,似乎每个函数都应该返自己的索引值,即位置 0 的函数返回 0,位置 1 的函数返回 1,以此类推。但实际上,每个函数都返回 10。因为每个函数的作用域链中都保存着createFunctions() 函数的活动对象,所以它们引用的都是同一个变量 i 。
我们可以通过创建另一个匿名函数强制让闭包的行为符合预期,如下所示。
javascript
function createFunctions() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = (function (num) {
return function () {
return num;
};
})(i);
}
return result;
}
在这个版本中,我们定义了一个匿名函数,并将立即执行该匿名函数的结果赋给数组。这里的匿名函数有一个参数 num ,也就是最终的函数要返回的值。在调用每个匿名函数时,我们传入了变量 i 。由于函数参数是按值传递的,所以就会将变量 i 的当前值复制给参数 num 。