Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setTimeout does not print consecutive numbers because of closure [duplicate]

Tags:

javascript

Possible Duplicate:
setTimeout in a for-loop and pass i as value

for (var i = 0; i < 5; i++) {
    setTimeout(function (i) {
        console.log(this.i)
    }, 1000);
}

This prints 5 five times. How can I write the loop so that it prints 0, 1, 2, 3, 4?

like image 442
Vamshi Vangapally Avatar asked Jan 23 '26 09:01

Vamshi Vangapally


2 Answers

Wrap it in a self-executing closure:

for (var i = 0; i < 5; i++) (function(i) {
    setTimeout(function() {
        console.log(i)
     }, 1000);
})(i);

Note: the argument to the function-expression to setTimeout is not being used, so I took that out. Also, it's not good to use global variables. Create variables using the var keyword.

You also don't need this.i; simply use i.

like image 86
David G Avatar answered Jan 25 '26 23:01

David G


Like this:

for (var i = 0; i < 5; i++) {
    (function (i) {
        setTimeout(function () {
            console.log(i)
        }, 1000);
    })(i);
}

The important factor here is that JavaScript only has function scope*, so the only way to create a scope that is different for every loop is to wrap the guts of the loop in a function. That way your setTimeout function creates a closure around i for that iteration of the loop.

EDIT:

* The let keyword is coming in ES6 which gives you the ability to declare a block scope local variable. Chrome 31 does not support it without enabling experimental features so be sure to check compatibility.

like image 34
Mike Valenty Avatar answered Jan 25 '26 22:01

Mike Valenty