我一直在熟悉javascript闭包并浏览了这篇文章 http://blog.morrisjohns.com/javascript_closures_for_dummies.html
由于关闭,示例5不能按预期工作。如何修改
result.push( function() {alert(item + ' ' + list[i])} );
使代码有效?
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
var item = 'item' + list[i];
result.push( function() {alert(item + ' ' + list[i])} );
}
return result;
}
function testList() {
var fnlist = buildList([1,2,3]);
// using j only to help prevent confusion - could use i
for (var j = 0; j < fnlist.length; j++) {
fnlist[j]();
}
}
testList();
谢谢!
答案 0 :(得分:6)
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
(function(i) {
var item = 'item' + list[i];
result.push(function() {
alert(item + ' ' + list[i]);
});
})(i);
}
return result;
}
答案 1 :(得分:3)
您需要来自不同函数的i
和item
作为不同范围内的单独变量(因此它们可以具有不同的值而不是共享)。由于Javascript只有函数作用域,因此需要创建一个包含这些变量的包装函数
function buildList(list) {
var result = [];
function make_f(item, i){
//item and i are now private variables of make_f
//and wont be shared by the returned closure
// the other variable in scope (list) is not shadowed so
// it is still shared but that is not a problem since we
// never change its value.
return function() { alert(item + ' ' + list[i]) };
}
for (var i = 0; i < list.length; i++) {
var item = 'item' + list[i];
result.push( make_f(item, i) );
}
return result;
}
您也可以使用立即调用的匿名函数((function(){}())
模式)执行相同的操作。
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
var item = 'item' + list[i];
result.push( (function (item, i){
return function(){function() {alert(item + ' ' + list[i])};
})(item, i) );
}
return result;
}
答案 2 :(得分:1)
把它放进......另一个封闭!
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
result.push((function(item, listItem){
return function() {
alert(item + ' ' + listItem);
};
})('item' + list[i], list[i]));
}
return result;
}
function testList() {
var fnlist = buildList([1,2,3]);
// using j only to help prevent confusion - could use i
for (var j = 0; j < fnlist.length; j++) {
fnlist[j]();
}
}
testList();
答案 3 :(得分:0)
var具有函数作用域,但如果使用let,则将获得块作用域。
所以我会做:
for(让我= 0;我