for循环中的jQuery延迟行为

时间:2012-11-15 08:48:35

标签: jquery jquery-deferred deferred

我最近问了一个关于for循环中延迟的jquery行为的问题。 Link here

我收到了一份有效的答案,但我不明白为什么会这样。

如果我有以下代码:

function update(callbacks) {
    return $.Deferred(function(dfr) {
        setTimeout(function() {
            callbacks.success()
        }, 1000);
        dfr.resolve();
    }).promise();
}

function updateElements(deferreds) {
    for (var i = 0; i < 5; i++) {
        (function() {
            var index = i;
            deferreds.push(update({
                success: function() {
                    alert(index);
                }
            }));
        })();
    }
};

(function() {
    var deffereds = [];
    updateElements(deffereds);
    $.when.apply($, deffereds).then(function() {}, function() {});
})();​

它返回5个警告窗口,其值为0到4.如果我将updateElements方法更改为:

function updateElements(deferreds) {
    for (var i = 0; i < 5; i++) {
        var index = i;
        deferreds.push(update({
            success: function() {
                alert(index);
            }
        }));
    }
};

它返回5个警报窗口,其值仅为4。有人可以解释一下这种行为吗?我很难理解差异的来源。

谢谢!

1 个答案:

答案 0 :(得分:3)

之所以这样做,是因为你已经用

关闭了一个循环
(function() {
        var index = i;
        deferreds.push(update({
            success: function() {
                alert(index);
            }
        }));
})();

此自执行块变为静态值,因为它没有传入外部值。如在链接的答案中,您需要传入该值。请注意在值结尾处给出值的关键区别IEFE(立即执行函数表达式)。对不起,但这需要强调。

(function(VALUE_ACCEPTED){
  //VALUE_ACCEPTED accepts the passed value of VALUE_PASSED
})(VALUE_PASSED)

这样你的代码就变成了这个:

function updateElements(deferreds) {
for (var i = 0; i < 5; i++) {
    (function(valueAccepted) { // valueAccepted = the passed in value from i
        var index = valueAccepted;
        deferreds.push(update({
            success: function() {
                alert(index);
            }
        }));
    })(i); // pass in i to valueAccepted
 }
};