[removed] closure of loop?

2019-01-03 07:14发布

I would like to do the something along the following:

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

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?

5条回答
▲ chillily
2楼-- · 2019-01-03 07:27
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/

查看更多
爷的心禁止访问
3楼-- · 2019-01-03 07:30

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);
}
查看更多
聊天终结者
4楼-- · 2019-01-03 07:44
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.

查看更多
聊天终结者
5楼-- · 2019-01-03 07:45

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).

查看更多
【Aperson】
6楼-- · 2019-01-03 07:54

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

查看更多
登录 后发表回答