简体   繁体   中英

Return a function from the anonymous wrapper?

I am trying to undrstand the code

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

from here http://bonsaiden.github.com/JavaScript-Garden/#function.closures

I understood this method :

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

Can anyone please help me by explaining the first one?

I will try to explain how I understands the first one,

first i is 0,
setTimeout is called,
self calling function "function(e)" is called with i=0,
Im stuck!! what happens when this function returns a function?

All the first one does is return a function that will be called after the timeout happens.

The purpose of it is to create a sub-scope for each iteration of the for loop so that the incrementing i isn't overridden with each iteration.

More explanation:

Lets take this apart into two different pieces:

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

This is the first piece:

for(var i = 0; i < 10; i++) {
    setTimeout(function(){
        console.log(i); //9-9
    },1000);
}

Now, when you run this loop, you will always get console.log()'s that contain 9 instead of 0 to 9. This is because each setTimeout is using the same reference to i .

If you wrap the setTimeout part of that in an anonymous function, it creates a scope for each iteration allowing each setTimeout to have it's own i value.

for(var i = 0; i < 10; i++) {
    setTimeout((function(i) {
        return function() {
            console.log(i); // 0-9
        }
    })(i), 1000)
}

The outer function inside the setTimeout gets executed immediately with an i of 0 for first iteration, 1 for second, etc. That function then in turn returns a function which is the function that setTimeout uses. A function is being generated and returned for each iteration of the loop using a different value for i .

Both end up with the same result: a setTimeout is called with a function to invoke, which writes a number from 0 to 9 on the console. Both use nested functions to get the current value of i into a closure so you don't end up logging 10 9's.

The first code chooses to have a function returning the function that setTimeout will call. The second changes the nesting order so that the closed-over function invokes setTimeout itself. The net effect is the same.

Other than stylistic reasons and personal choice, I don't see a reason to choose one over the other.

"Can you please check the updated question specifying where im getting confused"

OK, here's the long explanation. Remember that the first parameter to setTimeout() needs to be a reference to the function that you want executed after the specified delay. The simplest case is to just name a function defined elsewhere:

function someFunc() {
   console.log("In someFunc");
}

setTimeout(someFunc, 100);

Note there are no parentheses on someFunc when passing it as a parameter to setTimeout because a reference to the function itself is required. Contrast with:

setTimeout(someFunc(), 100);   // won't work for someFunc() as defined above

With parenthese it calls someFunc() and passes its return value to setTimeout . But my definition of someFunc() above doesn't explictly return a value, so it implicitly returns undefined - which is like saying setTimeout(undefined, 100) .

But it would work if changed someFunc() to return a function instead of returning undefined :

function someFunc() {
   return function() {
      console.log("In the function returned from someFunc");
   };
}

So now (at last) we come to the code from your question:

setTimeout((function(e) {
    return function() {
        console.log(e);
    }
})(i), 1000)

Instead of referencing a function by name and calling it as someFunc(i) it defines an anonymous function and calls it immediately as (function(e) {})(i) . That anonymous function returns another function and it is that returned function that becomes the actual parameter to setTimeout() . When the time is up it is that returned function that will be executed. Because the (inner) function being returned is defined in the scope of the (outer) anonymous function it has access to the e parameter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM