Closures and scope chain | Sololearn: Learn to code for FREE!
New course! Every coder should learn Generative AI!
Try a free lesson
+ 4

Closures and scope chain

Could someone help me out explaining why do I get 10 as a result in every array? function createfunc(){ var result = new Array(); for(var i=0; i<10; i++){ result[i] = function(){ return i; }; } return result; } there is an explanation for this in a book, it involves scope chain and stuff which I have no idea what it is.

26th Apr 2017, 7:58 AM
Donny Gozali
Donny Gozali - avatar
8 Answers
+ 6
run this code for example: function createfunc(){ // start of scope var result = new Array(); for(var i=0; i<10; i++){ result[i] = function(){ return i; }; } i++; // notice this return result; } // end of scope alert(createfunc()[0]()) // this prints the function stored in first index of the array notice that this code will now print 11 for each index that will be given in the alert what the code does is simply creating an array of functions. and each function does the same thing exactly --> returns the value of "i" now see where i marked //start of scope and // end of scope the variable "i" lives in that area and after the loop is done it still alive but have the same value of 10 (i incremented it once to just to show a point) in short, you created an array of 10 functions, each returning the same value
26th Apr 2017, 8:40 AM
Burey
Burey - avatar
+ 6
because you have one extra increment the one that stops the loop from excecuting again (i = 10)
26th Apr 2017, 10:01 AM
Burey
Burey - avatar
+ 4
I think you got all your answers already from @Burey but wanted to throw bit of light on scope and closures. First if you want to get the actual values from 0 - 9 then the function closure must be immediately invoked(IIFE) like below: function createFunction() { var result = new Array() // bad practice use literal instead for(var i=0; i < 10; i++) { result[i] = (function() { return i; })(); } return result; // [0, 1,.......9] } Now about why all the array elements are 10: it is because all the array elements just store a function which returns i without being executed. And since the last i value to terminate the loop is 10, the function then returns the last i value.
26th Apr 2017, 11:08 AM
Benneth Yankey
Benneth Yankey - avatar
+ 3
2. Well the case doesn't change but add up a little twist to scope when functions are nested within functions!. Consider below: function func() { var i = 2; function nestFunc() { return i * i; } // call inner function nestFunc(); } func(); // results 4 // magic! right From the above, the outer func creates a scope environment. Picture it like a dictionary with value-pairs {var i: 2, ......}. So the scope environment is created and the outer func finishes execution thinking that, the environment dies off too after execution... BUT nope! Later on when the nestFunc executes it creates its own scope environment too BUT still remembers or say has reference to its outer scope that's the environment created by the outer func. So its dictionary looks like this: {return: i * i,.....,{var i: 2}} So you can see that, the nestFuc stores the parent scope environment in its scope too. This is what is called Closure. The inner function closes or engulfs the parent scope as a reference in its scope environment. The code can be altered like this too to give you more insight: function func() { var i = 2; function nestFunc() { return i * i; } } Here you can see the inner function is not called!. This explains what I meant by the inner function executing later after the outer has finished. This means we can assign the outer function to a variable and call the inner function later. So from the above: var innerFunc = func(); The above returns the nestFun() to the variable so we can call it later as, innerFun(). // returns 4
26th Apr 2017, 11:50 AM
Benneth Yankey
Benneth Yankey - avatar
+ 3
@Donnzy exactly you got it right!, but you could also call it later as I have explained above.
26th Apr 2017, 12:01 PM
Benneth Yankey
Benneth Yankey - avatar
+ 2
Ohh I see, the first thing it does is inputing the function inside the array while keep incrementing without executing the content. But what still leave me hanging is why 10 and not 9? Thanks for your answer
26th Apr 2017, 9:57 AM
Donny Gozali
Donny Gozali - avatar
+ 2
A little info about scope and closures for basics: 1. Scope is just the environment where variables or contents can be accessed. e.g var i = 2; the scope of the above variable is the global environment because that's where it lives and can be accessed. function func() { var i = 0; } func(); Here the function func has the global environment as its scope. But the variable scope environment is within the function and only accessible from within the func function. Well until ES6 functions were the only means of creating a scope from separate from the global environment. Now we have 'let' for block scoping everywhere even in loops.
26th Apr 2017, 11:49 AM
Benneth Yankey
Benneth Yankey - avatar
+ 1
Wow thank you for your feedback guys. It's a pretty hard topic to understand, the explanation in the book makes it more confusing, it uses something like this for(var i=0; i<10;i++){ result[i] = function(num){ return function() { return num; }; }(i); return result; So the point that I captured here is function inside a function won't be executed unless you call it by using ()
26th Apr 2017, 11:58 AM
Donny Gozali
Donny Gozali - avatar