JavaScript中循环中闭包的区别

时间:2013-03-28 22:29:02

标签: javascript closures

这些功能有什么区别?为什么第一个工作,第二个不能按预期工作?

http://jsfiddle.net/GKDev/x6pyg/(这有效)

http://jsfiddle.net/GKDev/bv4em/(这不是)

我正在尝试遍历输入元素并在它们上添加onfocus事件:

for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];

    document.getElementById(item.id).onfocus = function() {
        showHelp(item.help);
    };
}

3 个答案:

答案 0 :(得分:2)

在非工作示例中,当调用匿名函数时,item具有for循环执行完后所持有的最后一个值。那是因为这个变量属于包含for循环的父函数。

在您的工作示例中,您创建了一个新函数,传递当前值item,如下所示:

function (help) {
            return function () {
                showHelp(help); // <-- This will be the value enclosed in this anonymous function
            };
        }(item.help); // <-- Calls an anonymous function passing in the current value

这会在该迭代期间存在一个围绕该值的新闭包。调用匿名函数时,它使用该本地值。

答案 1 :(得分:2)

它被视为:

var item;

for (var i = 0; i < helpText.length; i++) {
    item = helpText[i];

    document.getElementById(item.id).onfocus = function() {
        showHelp(item.help);
    };
}

在任何焦点回调触发之前,循环已完成,此时item是指定的最后一项。

答案 2 :(得分:1)

实际上很容易。

在第一种情况下,您将在闭包内传递item.help,该闭包充当本地副本。它就像一个范围的囚犯。外面发生了什么,无人问津。

for (var i = 0; i < helpText.length; i++) {
        var item = helpText[i];
        document.getElementById(item.id).onfocus = function (help) {
            return function () {
                showHelp(help);
            };
        }(item.help);
    }

在第二个中,没有闭包保留item的值,这意味着当item被计算时,它会计算到它的实际值,即:数组的最后一个元素,因为for set的最后一个循环它的值是数组的最后一个值。

for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
      showHelp(item.help);
    }
  }