1

Now of course, code only does what you make it do.

But i'm confused why in the following code:

var a = {
    0: "Hi",
    1: "Bye"
}

for (var b in a) {
    setTimeout(function () {
        console.log(b);
    }, 1000);
}

Instead of consoling "0" and then "1"

I just get "1" twice.

I'm not sure why that happens. I need a setup like that for a script I am making but I also get the same issue.

2 Answers 2

4

it is because your usage of closure is wrong.

In this case you are using the closure variable b inside the setTimeout callback, but the value of the variable b is not looked up until the callback is executed, by then the value of updated to the last value in the object.

One of the solution in such case is the create a local closure as given below

for (var b in a) {
    (function(c){
        setTimeout(function () {
            console.log(c);
        }, 1000);
    })(b)
}

Demo: Fiddle

Sign up to request clarification or add additional context in comments.

Comments

1

You can do it this way too

for (var b in a) {
    setTimeout(console.log.bind(console, b), 1000);
}

Or like this

for (var b in a) {
    setTimeout(function(c) {
        console.log(c)
    }.bind(null, b), 1000);
}

Or even like this

// compatibility varies
for (var b in a) {
    setTimeout(function(c) {
        console.log(c)
    }, 1000, b);
}

4 Comments

More like setTimeout(console.log.bind(console, b)
@Musa, console.log.bind(null, b) works in this scenario too. console.log does not need its own context to work.
So you don't get Illegal Invocation?
@Musa, hmm, in node-0.10.12 it works with null, but in browser it looks like it requires console. Thanks for catching this dissimilarity. I only do node work so I never noticed :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.