JavaScript closure loop issue in set time out

陌路散爱 提交于 2019-12-02 11:56:27

问题


I've found some example in a tutorial (said it was the canonical example)

        for (var i=1; i<=5 ; i++) {
        setTimeout(function() {
            console.log("i: " + i);
        }, i*1000);
    }

Now, I understand that, closure passes in the current scope in to the function, and I assume that it should output 1,2,3,4,5. But instead, it prints number 6 five times.
I ran it in the chrome debugger, and first it goes through the loop without going in to the function while doing the increment of the i value and only after that, it goes in to the inner function and execute it 5 times.
I'm not sure why its doing that, I know, the current scoped is passed in to the function because of closure, but why does it not execute each time the loop iterate?


回答1:


By the time the timeout runs, the for loop has finished, and i is 6, that's why you're getting the output you see. You need to capture i during the loop:

for (var i=1; i<=5 ; i++) {
    (function(innerI) {
        setTimeout(function() {
            console.log("i: " + innerI);
        }, innerI*1000);
    })(i);
}

This creates an inner function with it's own parameter (innerI), that gets invoked immediately and so captures the value of i for use within the timeout.




回答2:


If you didn't want the complex-looking IIFE as explained in James' answer, you can also separate out the function using bind:

function count(i) {
    console.log("i: " + i);
}

for (var i = 1; i <= 5; i++) {
    setTimeout(count.bind(this, i), i * 1000);
}



回答3:


Thank you for you help, I found out another solution and it was a minor change.

On the top of the page I turned on the strict mode and also in the for loop, Instead of var, I used the "let" keyword.



来源:https://stackoverflow.com/questions/29795666/javascript-closure-loop-issue-in-set-time-out

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!