0

I'm a javascript newbie trying to wrap my mind around this code. I got it here http://brackets.clementng.me/post/24150213014/example-of-a-javascript-closure-settimeout-inside

I still have a hard time understanding it. Since it involves some pattern I'm not familiar with.

// output 0-9, seperated by 1 sec delay.
for (var i = 0; i < 10; i++) {
    setTimeout(function(x) { 
        return function() { 
            console.log(x); 
        }; 
    }(i), 1000*i);
}

What is the meaning of (i) in this section of code?

function(x) { 
    return function() { 
        console.log(x); 
    }; 
}(i)

I thought it is an immediately invoked function expression. But isn't the correct syntax for that is:

(function() {
  // some code
})();
  • if anyone interested here is another explanation for the same code. http://stackoverflow.com/questions/12930272/javascript-closures-vs-anonymous-functions?rq=1 – willy teng Jul 22 '15 at 04:51

3 Answers3

2

That is, indeed, an IIFE. The syntax you quote is an IIFE of 0 arguments; the syntax you asked about is an IIFE of 1 arguments. It will assign i to x in the inner code. Compare:

var print0 = function() {
  console.log("Hello!");
};
print0();

is (in isolation) equivalent to

(function() {
  console.log("Hello!");
})();

Thus the name: you create a function, then immediately invoke it.

However, if you want an argument, nothing really changes:

var print1 = function(name) {
  console.log("Hello, " + name);
};
print1("George");

is (in isolation) equivalent to

(function(name) {
  console.log("Hello, " + name);
})("George");

The parentheses here ensure that the function definition will be taken as an expression rather than as a statement. There are other ways to ensure that, a common one being

!function() {
  console.log("Hello!");
}();

(But there are reasons to prefer the parentheses.) Since you are using it as an argument to the setTimeout call, it can't possibly be a statement, so these hacks are not necessary. It is still called "immediately invoked function expression", since you are still constructing a function expression and immediately invoking it.

The reason why an IIFE is used here is to "capture" the value of the variable i, rather than the location of x. Without the closure trick, you would get 10 timeouts, all outputting 10 (the value of the location denoted by x when the console.log resolves).

Amadan
  • 169,219
  • 18
  • 195
  • 256
0

Yes it is, and the (i) is the argument list for the call. Have a look here for a detailed explanation. The grouping parenthesis are unncessary in this case, as it is an argument to the setTimeout function call and therefore an expression anyway.

The term IIFE does not only refer to the statement form of this pattern, where the parenthesis would be necessary.

Community
  • 1
  • 1
Bergi
  • 513,640
  • 108
  • 821
  • 1,164
0

The parantheses are optional in your example of an immediately invoked function.

(function() {
  // some code
})();

Can be re-written as

function() {
  // some code
}();

So the i in the example function's call becomes the x in the function definition.

function(x) { // x = 1
    return function() { 
        console.log(x); // x = 1
    }; 
}(1)
nivix zixer
  • 1,461
  • 1
  • 11
  • 19