作为一个javascript初学者,直到看到下面示例代码中的陷阱,我才意识到Closure特性。我试图修改代码以弹出许多C/c++/c#/Java程序员期望的结果,
" item1 1"
"第二条2"
" item3 3 "
挣扎了一个小时,我还是做不到。哪位javascript大师能教我怎么修改它吗?谢谢你。
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();
这个想法是创建一个闭包,它将被固定在里面。
- 你可以嵌套
for
的内容在一个直接的函数:
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
(function(k){// k will equals i
var item = 'item' + list[k];
result.push( function() {alert(item + ' ' + list[k])} );
})(i);// i in argument
}
return result;
}
function testList() {
var fnlist = buildList([1,2,3]);
for (var j = 0; j < fnlist.length; j++) fnlist[j]();
}
testList();
与编写其他函数相同:
function doStuff(k,arr,arr2){
var item = 'item' + arr[k];
arr2.push( function() {alert(item + ' ' + arr[k])});
}
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) doStuff(i,list,result);
return result;
}
function testList() {
var fnlist = buildList([1,2,3]);
for (var j = 0; j < fnlist.length; j++) fnlist[j]();
}
testList();
- 使用最近的
forEach(value, index, array)
方法自动提供闭包: - 使用ECMAScript 6
let
(thanks elad.chen)
function buildList(list) {
var result=[];
list.forEach(function(e){
result.push(function(){alert('item'+e+' '+e)});
});
return result;
}
buildList([1,2,3]).forEach(function(e){e();});
相当酷。
let
可以代替var
来作用域i
在循环中的函数中:不再需要像(1)和(2)那样创建闭包。您只需要将item+list[i]
部分移动到函数中。然而,let
仅在严格模式下可用,而不是在所有浏览器中(例如,它仍然错过firefox)
'use strict'
function buildList(list) {
var result = [];
for(let i=0;i<list.length;i++) {
result.push(function(){alert('item'+list[i]+' '+list[i])});
}
return result;
}
function testList() {
var fnlist = buildList([1,2,3]);
for (var j = 0; j < fnlist.length; j++) fnlist[j]();
}
testList();
绝不是高手,只是学习而已:
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]);
}
testList();
这可能是IIFE使用的好机会。演示:http://jsfiddle.net/zh02a69j/2/
当您通过fnlist[j]()
调用第一个函数时,您的i
值是最后增加的值。你的函数将结果推到数组'看到'只是那个值,因为它没有立即执行,在循环中-它被定义,但没有执行。您可以让它立即执行(如IIFE),在循环中,然后脚本返回预期的输出。
如果我犯了一些错误(致所有以前和将来的反对者:))-也请指导我。