代码之家  ›  专栏  ›  技术社区  ›  Hortitude

javascript闭包示例

  •  0
  • Hortitude  · 技术社区  · 13 年前

    我在这个网站上阅读关于闭包的说明: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])}添加 对匿名函数的引用 三次到结果数组。如果 你对anonymous不太熟悉 函数可以这样认为: pointer=function(){alert(item+''+list[i])}; 结果。按下(指针);

    请注意,在运行示例时, “项目3未定义”被警告3 时代!这是因为就像 以前的例子只有一个 局部变量的闭包 构建列表。当匿名者 函数是在线调用的 他们都用同样的方法 单闭包,他们使用 i和项的当前值 一个结束(我有一个价值 因为循环已经完成了, 项的值为“item3”。

    是否有“正确”的方法来获得javascript中的“预期”行为?

    谢谢!

    2 回复  |  直到 13 年前
        1
  •  3
  •   deceze    13 年前
    result.push((function (jtem, j) {
       return function() { alert(jtem + ' ' + list[j]); }
    })(item, i));
    

    创建一个引入新变量作用域的匿名函数。立即执行该函数,传递变量,这些变量将成为新变量 jtem j 在一个新的范围内,因此 item i 是“坏的”。然后返回实际的函数,该函数现在使用不同的变量(可以保留名称 项目 ,我只是为了说明的目的更改了它们)。

        2
  •  1
  •   Matt    13 年前

    是的,您将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没有块范围,而是由函数捕获的词法范围。为了解决这个问题,您可以创建另一个函数,如上面所示,从而将变量捕获到一个不受循环影响的新范围中。