1

Hi I am new to javascript and I cannot understand the following code:

var createAdders = function () {

    var fns = [];

    for (var i = 1; i < 4; i++) {

        fns[i] = (function (n) {
            return i + n;
        });
    }
    return fns;
}
var adders = createAdders();
adders[1](7); //11 ??
adders[2](7); //11 ??
adders[3](7); //11 ??

From what I understand 7 is being passed as an argument but createAdders() doesn't assign 7 to any variable so does that mean 7 is being passed to the very next function within createAdders() i.e the anonymous function and assigned to the variable n.

Is my logic correct?

The code above does seem to work but for every call the result is 11. I found this code in a very reliable blog as an example to a situation where closures would be useful.The above code is then altered in the following way to cite the advantages of closures.

var createAdders = function () {
    var fns = [];
    for (var i = 1; i < 4; i++) {
        (function (i) {
            fns[i] = (function (n) {
                return i + n;
            });
        })(i)     //// why is (i) used here? what purpose does it serve??////
    }
    return fns;
}

var adders = createAdders();
adders[1](7); //8 
adders[2](7); //9 
adders[3](7); //10

Is the same logic applied here as well?

I need to understand how n is being assigned the value 7

Why is (i) being used at the end of the function in the new code?

3
  • I'm intermediate in JS, and I cannot understand what's the 'n' too =)) Commented Nov 19, 2012 at 17:27
  • The n is the argument being passed when the function is called. Commented Nov 19, 2012 at 17:28
  • This was a nice read : developer.mozilla.org/en-US/docs/JavaScript/Guide/… Commented Nov 19, 2012 at 21:12

3 Answers 3

2

In JavaScript, we don't have block scope, only function scope.

In the first example, the only i declared belongs to the createAdders scope, meaning all functions created in the for loop will seek up in the scope chain the same i and return the same value. Explained with code:

//   here's the only `i` declaration
for (var i = 1; i < 4; i++) {

    fns[i] = (function (n) {
        return i + n; //this line will retrieve the `i` variable declared above,
                      //that being always 4 after the loop ends
    });
}

In the second example, you're creating a new scope with an IIFE inside the loop - it creates a new execution context for each iteration.

A function created inside of the IIFE will access the IIFE's execution context's i. This i is unique for each iteration as you're passing the outer i to the IIFE, which becomes the IIFE's formal parameter i.

In short, each iteration creates a new execution context with its own i through an IIFE wrapper.

Read the comments in order:

//  1. Outer `i` declared here
for (var i = 1; i < 4; i++) {
    (function (i) {// 3. Outer `i` becomes the formal parameter `i` of the IIFE, 
                   // it is a "different" `i` in a new execution context (scope)
        fns[i] = (function (n) {
            return i + n; // 4. seeks the `i` value of the IIFE
        });
    })(i) // 2. Outer `i` passed to IIFE
}

When you invoke the function(s) created inside of the IIFE, the scope chain will retrieve the "closest" i in the scope chain, that being the formal parameter i of the IIFE in which the function was created.

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

2 Comments

stop editing please. I am trying to read. :(
Was trying to make it easier to read. :P
1

In the first block, the createAdders() return an array of functions, and every function (created in the inner for loop of the createAdders() function body) sums the parameter n (the 7 value) with the variable i created in the loop, wich, at the end of the loop, has the value of 4 (that explains the 11).

When you made the invocation adders[1](7) the function stored in the array fns at position 1 is returned, then you invoke the function with the parameter n = 7, then the function proceeds to sum this parameter with the i variable of the createAdders function (which value is 4 at the moment invoke adders[1](7))

Comments

0

In javascript , inner function always have access to their outer function variable even after the outer function is finished executing. This behaviour is called Closure.

In first snippet, you're iterating over 3 times and pushing the function inside an array.When the loop is finished executing your variable i is set to 4. And function you pushed inside the array has access to this variable . So no matter at what index of array you execute the function you always get 11 ( 4 + 7).

In Second snippet , you are using an self executing anonymous function to hold the value of i . This anonymous function gets immediately executed with every interation . Because of closure function defined inside this anonymous function has a reference to new value of i every time.

So you have a three function inside the array each with seperate value of i (1,2,3) Writing second snippet as follows makes it more clear

var createAdders = function(){
var fns = [ ];
for (var i=1; i<4; i++) { 
    (function(a) {
        fns[a] = (function(n) {
            return a+n;
        });
    })(i)    
}
return fns;}

In javascript you can have function as return value. and secondly arrays can store function inside themself.

What your doing in code is pushing a function inside array which accepts a single argument and later invoking it.

adders[1](7);

can be broken down as follow

var fn = adders[1];
fn(7); //thats how n is set to 7

2 Comments

Self Executing is not the same as Immediately Invoked. Self executing is associated with recursion, a function that calls itself as in function foo() { foo(); }, meanwhile an IIFE (Immediately Invoked Function Expression) is what it says, a function expression that is immediately invoked: (function(i){})(i) as well as (function(i){}(i)). It is a small misinformation, but as many people also have this mis-info of calling IIFEs as self-executing - which they are not, unless it calls itself as in (function foo(i){ foo(i+1); }(i)) -, it's a thing worth mentioning.
Thanks, I did thought they both mean the same thing

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.