【问题标题】:Closures affecting variables in a closed function within a loop闭包影响循环内封闭函数中的变量
【发布时间】:2012-04-01 07:32:14
【问题描述】:
this.config = {
    source: psource,
    _events: [
        'value1',
        'value2',
        'value3'
    ]
};

// Add callbacks to source
var that = this;
for (var i = this.config._events.length - 1; i >= 0; i--) {
    var name = this.config._events[i];
    console.log(name); // correct

    $(this.config.source).on(name, function() {
        console.log(name); // value1
        console.log(that.config._events[i]); // undefined
    });
}

我看不出这里有什么问题。我删除了所有复杂的版本并放入了最简单的版本,它根本不想工作。第一个console.log 正确输出了所有正确的名称,但它的作用就像循环同时发生,然后对内部console.log 再次执行。

谁能看出问题所在?

【问题讨论】:

  • “闭包影响一切,而不仅仅是这个”这句话并不是在描述问题——这就是闭包的工作原理。封闭范围内的所有变量都包含在闭包中。
  • 请用更具描述性的内容修改问题的标题。我认为您应该提到术语for loop

标签: javascript loops for-loop closures


【解决方案1】:

在那个街区

console.log(that.config._events[i]); // undefined

i 会在每次调用闭包时为 -1。

你必须做一些事情才能在i周围创建一个闭包

$(this.config.source).on(name, function(i) { return function() {
        console.log(name); // value1
        console.log(that.config._events[i]); // undefined
    };
}(i) );

【讨论】:

  • 更好的是,将i 作为参数传递给.on 方法,并使用event.i 访问变量。有关我的建议的更多详细信息,请参阅.on() 的文档:api.jquery.com/on
  • @RobW 这可能适用于这种情况,因为 i 是一个数字原语。但是,我特意选择了这个解决方案,以便操作人员能够理解,在闭包中保留对变量的引用并不等同于在创建闭包时保留对它的当前值的引用。
【解决方案2】:

在 Javascript 中,不建议在 for 循环内定义函数。

相反,您应该使用提供 each 的 javascript 库,例如underscore。然后您的代码将如下所示:

    _.each(this.config._events, function(e) {
       $(this.config.source).on(name, function() {
          console.log(e);
       });

您之前可能想要反转数组。

这里是doc for _.each

您也可以使用 jQuery 的$.each,它提供了类似的界面。

【讨论】:

  • -1 在for 循环中定义函数是非常安全的。您只需要了解变量范围以及闭包的工作原理。
  • 我将not safe 替换为dangerous。这会导致很多混乱。事实上,jslint 不允许这样做。请投票支持
  • 也没有什么危险的。它可以正常工作。我支持我的-1。 jslint 不允许这是他们的选择,而不是 JavaScript 问题。
猜你喜欢
  • 1970-01-01
  • 2014-12-04
  • 2019-08-02
  • 2021-02-16
  • 2014-10-23
  • 2016-12-14
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多