JAVASCRIPT QUESTION... 🤔 | Sololearn: Learn to code for FREE!
New course! Every coder should learn Generative AI!
Try a free lesson
+ 11

JAVASCRIPT QUESTION... 🤔

What is the output of this code and why is it that way? https://www.sololearn.com/post/662769/?ref=app

12th Oct 2020, 1:22 PM
👑 Tchybooxuur!
👑 Tchybooxuur! - avatar
21 Answers
+ 8
👑 Tchybooxuur! The output is 3 3 3 and not 0 1 2 as one would expect, due to scope and closure. The variable i in addArr function has function scope due to it being declared using the keyword var.Thus effectively,addArr has only one declaration of i.An alternative representation of the code you've given above could look something like this function addArr(){ var arr=[]; var i; for(i=0;i<3;i++){ /*The rest of your code*/ }} Now keep in mind that the functions stored in arr never hold a copy of i.This is not what closure is about Whenever an inner function obtains closure over another function,the JS engine only prolongs the lifetime of those local variables.It never assigns a new copy to each new function. Thus all the three functions,will access the same variable i when called,as they acquire closure of the inner scope of addArr function that has only one i. I presume that I don't need to explain why i is 3 since I assume that you are already familiar with how loops work. Hence the output is 3 3 3
13th Oct 2020, 4:14 PM
Anthony Maina
Anthony Maina - avatar
+ 6
There are 2 ways of fixing this. 1.Using let as 🇮🇳Vivek🇮🇳 has just shown.Let introduces block scopes.Thus a new variable i is created at the start of each iteration and "destroyed" at that iteration's exit.Now all functions in arr will have closure over different i variables.(This might seem confusing at first but think about it deeply,you'll eventually see the logic) 2.If you insist on using var then you'll have to do what many JS programmers wrongly assume the engine does for them - create a copy of i yourself that is local to each new function!.I.e. function addArr(){ /*part of your code*/ for(var i=0;i<3;i++){ arr.push(function (){ var j=i; //j is now a copy of i console.log(j); }); } /*The rest of your code*/
13th Oct 2020, 4:40 PM
Anthony Maina
Anthony Maina - avatar
+ 5
Anthony Maina Thanks a lot for your explanations. They are very helpful. The second explanation is yet to totally sink though but I'll go through it a couple more times and hopefully it sinks for good.
13th Oct 2020, 4:48 PM
👑 Tchybooxuur!
👑 Tchybooxuur! - avatar
+ 5
Anthony Maina I think your first answer and fix 1 of the second have successfully solved this question👍 However the second fix won't work because of the same reason you stated in your first answer. If you want other alternatives you could: 1-) Use an IIFE to capture the value of "i" on each iteration and make our function enclose that value. Example: arr.push( (function(i){ return function(){ console.log(i); })(i) ) // end push 2-) Add a parameter to the original function and bind "i" to it: arr.push( function(i){ console.log(i) }.bind(null,i) ) // End push
13th Oct 2020, 7:27 PM
Kevin ★
+ 4
🇮🇳Vivek🇮🇳 The original code is using var instead let you which produces a different result. 3, 3, 3
12th Oct 2020, 5:11 PM
ODLNT
ODLNT - avatar
+ 3
ODLNT oh. I didn't realise that. Question is in es5.
12th Oct 2020, 5:16 PM
🇮🇳Vivek🇮🇳
🇮🇳Vivek🇮🇳 - avatar
+ 3
🇮🇳Vivek🇮🇳 😅 Nice try. let was not used in the question.
12th Oct 2020, 5:20 PM
👑 Tchybooxuur!
👑 Tchybooxuur! - avatar
+ 3
ODLNT It would have been nicer if you tendered your own explanation.
12th Oct 2020, 5:21 PM
👑 Tchybooxuur!
👑 Tchybooxuur! - avatar
+ 3
🇮🇳Vivek🇮🇳 I had the same urge to use let, but then from out of no where I heard the words "block scope"😉
12th Oct 2020, 5:22 PM
ODLNT
ODLNT - avatar
+ 3
Théophile I don't think you are right.
12th Oct 2020, 5:22 PM
👑 Tchybooxuur!
👑 Tchybooxuur! - avatar
+ 3
Théophile I'm not sure how to answer your question too... 😅😅😅 What is actually going on under the hood is a feature in Javascript and some other languages like python called closures. The final value of i in the for loop is what's available in memory in the execution context of addArr which is 3. And it gets called 3 times.
12th Oct 2020, 5:40 PM
👑 Tchybooxuur!
👑 Tchybooxuur! - avatar
+ 3
Théophile: 😅🤣 Now you get it. 'i++' still increases i to 3 before the loop terminates. For loops in js and python are different. For loop in python works with a preset range of values while the for loop in js works like a while loop in some sense.
13th Oct 2020, 9:32 AM
👑 Tchybooxuur!
👑 Tchybooxuur! - avatar
+ 2
Théophile the main difference between var and let is var has weird part. But let doesn't have. So, people recommend to use let or const and not to use var. variable declared with var is globally scoped. but variable declared with let and const is block scoped. I don't know why it is giving 3, 3, 3 in console. Technical it should give 0, 1, 2.
12th Oct 2020, 10:55 PM
🇮🇳Vivek🇮🇳
🇮🇳Vivek🇮🇳 - avatar
+ 2
🇮🇳Vivek🇮🇳 I knew it is a better to use 'let' to declare variables, but the two different output here are quite surprising. 🤔 👑 Tchybooxuur! with 'var', it seems to work like in python, indeed. In my first comment, I wrote 2 2 2 as the answer because I'm it would have been the result in Python 😅. I completely forgot the last 'i++' in the JS code.
13th Oct 2020, 5:13 AM
Théophile
Théophile - avatar
+ 2
Anthony Maina Thanks. You really help me to understand this.
13th Oct 2020, 4:17 PM
🇮🇳Vivek🇮🇳
🇮🇳Vivek🇮🇳 - avatar
+ 2
Kevin ★ Yeah you're right
13th Oct 2020, 7:36 PM
Anthony Maina
Anthony Maina - avatar
+ 1
I'm not sure at all, but since we capture the variable i, then the result would be 2 in each function call. (it answer from my Python experience and I assume it behaves as lambda in Python).
12th Oct 2020, 3:02 PM
Théophile
Théophile - avatar
+ 1
This because i is 0, 1, 2. And we are logging into console. https://code.sololearn.com/cNoatM1oGofU/?ref=app
12th Oct 2020, 4:53 PM
🇮🇳Vivek🇮🇳
🇮🇳Vivek🇮🇳 - avatar
+ 1
👑 Tchybooxuur! Indeed... I tried to answer with my python knowledge. And I have to acknowledge that I don't understand the output here 😅. I thought it was capturing the variable 'i', and not the value of 'i'. 🤔
12th Oct 2020, 5:26 PM
Théophile
Théophile - avatar
+ 1
Oh! I realized that there is a difference between 'let' and 'var'. With 'let', the output is 0 1 2 and with 'var', it is 3 3 3... That's weird... 'var' declare 'i' for the whole function scope, while 'let' declares it for the loop scope only. Does that means that with 'var', the variable is captured, and with 'let', the value is copied?
12th Oct 2020, 5:30 PM
Théophile
Théophile - avatar