开发者

Javascript: closure of loop?

开发者 https://www.devze.com 2023-02-22 11:25 出处:网络
I would like to do the something along the following: for (var i = 0; i < 10; ++i) { createButton(x, y, function() { alert(\"button \" + i + \" pres开发者_StackOverflow社区sed\"); }

I would like to do the something along the following:

for (var i = 0; i < 10; ++i) {
    createButton(x, y, function() { alert("button " + i + " pres开发者_StackOverflow社区sed"); }
}

The problem with this is that I always get the final value of i because Javascript's closure is not by-value.

So how can I do this with javascript?


One solution, if you're coding for a browser that uses JavaScript 1.7 or higher, is to use the let keyword:

for(var i = 0; i < 10; ++i) {
    let index = i;
    createButton(x, y, function() { alert("button " + index + " pressed"); }
}

From the MDC Doc Center:

The let keyword causes the item variable to be created with block level scope, causing a new reference to be created for each iteration of the for loop. This means that a separate variable is captured for each closure, solving the problem caused by the shared environment.

Check out the MDC Doc Center for the traditional approach (creating another closure).


for(var i = 0; i < 10; i++) {
    (function(i) {
        createButton(function() { alert("button " + i + " pressed"); });
    })(i);
}

Note that JSLint doesn't like this pattern. It throws "Don't make functions within a loop.".

Live demo: http://jsfiddle.net/simevidas/ZKeXX/


Create a new scope for the closure by executing another function:

for(var i = 0; i < 10; ++i) {
    createButton(x,y, function(value) { return function() { alert(...); }; }(i));
}

http://www.mennovanslooten.nl/blog/post/62


You need to put the closure into a separate function.

for(var dontUse = 0; dontUse < 10; ++dontUse) {
    (function(i) {
        createButton(x, y, function() { alert("button " + i + " pressed"); }
    })(dontUse);
}

Thise code creates an anonymous function that takes i as a parameter for each iteration of the loop.
Since this anonymous function has a separate i parameter for each iteration, it fixes the problem.

This is equivalent to

function createIndexedButton(i) {
    createButton(x, y, function() { alert("button " + i + " pressed"); }
}

for(var i = 0; i < 10; ++i) {
    createIndexedButton(i);
}


for(var i = 0; i < 10; ++i) {
    createButton(x, y, (function(n) {
        return function() {
            alert("button " + n + " pressed");
        }
    }(i));
}

The anonymous function on the outside is automatically invoked and creates a new closure with n in its scope, where that takes the then current value of i each time it's invoked.

0

精彩评论

暂无评论...
验证码 换一张
取 消