1

我有这个示例代码:

for (var i = 0; i < array.length; i++) {
    $.getJSON("http://someapi", { "one": two }, function (result) {
        array[i].value = result.value;
    });
}

然而,回调函数中的 i 变量并不符合预期。for 循环运行得非常快,并且在第一个回调函数收到答案之前完成,因此 i 变量位于循环中的某个位置,甚至完成并超过了数组边界。

无论如何,有没有办法将变量传递给回调函数?像这样的东西:

$.getJSON("http://someapi", { "one": two }, function (result, i) {
    array[i].value = result.value;
});
4

2 回答 2

4
for (var i = 0; i < array.length; i++) {
    $.getJSON("http://someapi", { "one": two }, (function(j) {
        return function (result) {
            array[j].value = result.value;
        };
    })(i)); // Immediate invocation is your best friend
}

像这样,您可以i在声明回调时传递变量(而不是像在代码中那样评估它时)。

于 2013-04-11T10:22:05.290 回答
3

Creating an additional closure to store the current index and using that inside your actual function should do the trick, similar to this:

for (var i = 0; i < array.length; i++) {
    $.getJSON("http://someapi", {
        "one": two
    }, (function () { // added closure...
        var currentIndex = i; //...to allow declaration of additinal variables

        return function (result) {
            array[currentIndex].value = result.value; // use currentIndex here
        };
    })()); // () force immidiate execution
}

DEMO - Comparing results between not using a closure and using a closure


Open the DEMO and then click Run, watching the console outputs.

Code from DEMO:

var array = [1, 2, 3, 4, 5];

// Wihtout closure i is not always as expected.
for (var i = 0; i < array.length; i++) {
    $.getJSON("#", {
        "one": 1
    }, function (result) {
        console.log('no-closure: ' + i);
    });
}

// With closure stored i (currenIndex) is in the expected order
for (var i = 0; i < array.length; i++) {
    $.getJSON("#", {
        "one": 1
    }, (function () {
        var currentIndex = i;
        return function (result) {
            console.log('closure: ' + currentIndex);
        };
    })());
}
于 2013-04-11T10:26:35.840 回答