javascript闭包示例

时间:2010-11-22 03:19:15

标签: javascript

我正在阅读本网站以获取有关关闭的说明:blog.morrisjohns.com/javascript_closures_for_dummies.html

它有以下例子:

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]();
  }
}

他们的笔记(正确地)指出:

  

行result.push(function()   {alert(item +''+ list [i])}添加了一个   引用匿名函数   三次到结果数组。如果   你不是那么熟悉匿名   功能想到它:       pointer = function(){alert(item +''+ list [i])};       result.push(指针);

     

请注意,运行示例时,   “item3 undefined”被警告三   倍!这是因为就像   以前的例子,只有一个   关闭局部变量   buildList。当匿名   函数在线上调用   fnlistj;他们都使用相同的   单关,他们使用   i和项目的当前值   那一个闭包(我有一个值   因为循环已经完成,   和item的值为'item3')。

是否有一种“正确”的方式来获取javascript中的“预期”行为?

谢谢!

2 个答案:

答案 0 :(得分:3)

result.push((function (jtem, j) {
   return function() { alert(jtem + ' ' + list[j]); }
})(item, i));

您创建了一个匿名函数,它引入了一个新的变量范围。您立即执行该函数,传递变量,这些变量在新范围内成为新变量jtemj,因此与itemi的“连接”是“破碎”。然后返回实际的函数,现在使用不同的变量(您可以保留名称iitem,我只是为了说明目的而更改它们。)

答案 1 :(得分:1)

是的,您将i的值赋给另一个变量,以便变量可以成为闭包的一部分。

function buildList(list) {
  var result = [];
  for (var i = 0; i < list.length; i++) {
    var item = 'item' + list[i];
    result.push(function(cItem, index){ 
       return function(){ alert(cItem + ' ' + list[index]); }
    }(item, i));
  }
  return result;
}

原因是JavaScript没有块范围,而是一个由函数捕获的词法范围。要解决这个问题,可以创建另一个函数,如上所示,从而将变量捕获到一个不受循环影响的新范围。