【问题标题】:Issue getting closures to work [duplicate]问题让关闭工作[重复]
【发布时间】:2016-08-16 07:10:44
【问题描述】:

我有一段代码试图提醒1,2,3。我在正确使用闭包时遇到问题,所以我无法弄清楚。

原代码:

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

我正在尝试对buildList() 执行类似操作以使其正常工作:

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

我知道我在使用闭包时犯了错误,我只是不确定问题出在哪里。

【问题讨论】:

    标签: javascript closures


    【解决方案1】:

    您的第二次尝试更接近解决方案,但仍然无法正常工作,因为您的最内层函数正在从您的顶级函数中捕获变量 itemitem 始终引用创建的同一个实例拨打buildList()时。

    JavaScript 中的var 作用域始终绑定到当前函数调用,而不是代码块,因此它不绑定到像for 这样的控制语句。

    因此,警报可能会显示'item' + (list.length-1) 在调用buildList() 时的值。

    由于您将i 传递给您的闭包,您应该在该函数中声明var item,例如:

    function buildList(list) {
        var result = [];
        for (var i = 0; i < list.length; i++) {
            result[i] = function(x) {
                // x and item are both local variables of anonymous function declared just above
                var item = 'item' + list[x]; // or maybe you meant 'item' + x?
                return function() {alert(item + ' ' + list[x])};   
            }(i);
        }
        return result;
    

    }

    请注意,闭包仍将捕获对list 的引用,因此将在调用buildList() 返回的数组中的函数时显示它包含的值。局部变量item 也是完全可选的,你可以调用alert('item' + x /*or is it list[x]?*/ + ' ' + list[x])

    【讨论】:

      【解决方案2】:

      来自How do JavaScript closures work?

      请注意,当您运行示例时,“item2 undefined”会被警告三个 次!这是因为就像前面的例子一样,只有一个 buildList 的局部变量的闭包。当匿名 在 fnlistj 行上调用函数;他们都使用相同的 单个闭包,它们使用 i 和 item 的当前值 那个闭包(其中 i 的值为 3,因为循环有 已完成,并且 item 的值为“item2”)。请注意,我们正在索引 0 因此 item 的值为 item2。并且 i++ 会将 i 增加到 值 3。

      如果要存储i的匹配值,则需要在每次循环迭代中进行闭包:

      function buildList(list) {
        var result = [], item, closure;
        for (var i = 0; i < list.length; i++) {
          item = 'item' + list[i];
      
          // call this function with the string you wish to store
          // the inner function will keep a reference to the 'msg' parameter even after the parent function returns
          closure = (function(msg) {
              return function() {
                alert(msg);
              };
            }(item + ' ' + list[i]));
          result.push( closure );
        }
        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();
      

      herehere 提出了同样的问题。相同的答案herehereherehere 可能还有十几个地方。

      【讨论】:

        猜你喜欢
        • 2022-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多