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?

Sahil
  • 107
  • 1
  • 6

3 Answers3

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.

Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166
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))

higuaro
  • 15,730
  • 4
  • 36
  • 43
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
deven98602
  • 1,090
  • 9
  • 19
  • 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. – Fabrício Matté Nov 19 '12 at 18:41
  • Thanks, I did thought they both mean the same thing – deven98602 Nov 19 '12 at 18:44