Closed ajfg93 closed 4 years ago
If anything confuses you, do tell! I will try my best! :-)
If I understand correctly, using
let
doesn't create a new Lexical Environment and it is the{}
block clause creates a new Lexical Environment each time andlet
just creates a local variable inside the Lexical Environment, whilevar
hoists the variable into the function level scope when creating a variable. So, whether usinglet
or not, there is a new Lexical Environment created each run infor(){}
orwhile{}
That's correct!
But for the first time I read the solution/explanation, I thought it was using let that creates a new Lexical Environment.
You should read the solution again. It explains correctly! Below is the code snippet from task - https://javascript.info/task/make-army.
function makeArmy() {
let shooters = [];
let i = 0;
while (i < 10) {
let shooter = function() { // shooter function
alert( i ); // should show its number
};
shooters.push(shooter);
i++;
}
return shooters;
}
let army = makeArmy();
army[0](); // the shooter number 0 shows 10
army[5](); // and number 5 also outputs 10...
// ... all shooters show 10 instead of their 0, 1, 2, 3...
And becasue you are adding a new
let
or replacingvar
withlet
in each new code snippet. [...]
As you can see above, variable i
is declared using let
, not var
. Another thing to note is that, we are actually pushing a function to shooters
array, not a value. What that means is, whenever a shooter function is called, value of i
is taken from its lexical environment (see below).
From solution:
Now why all such functions show the same? That’s because there’s no local variable
i
inside shooter functions. When such a function is called, it takesi
from its outer lexical environment.--snip--
…We can see that it lives in the lexical environment associated with the current
makeArmy()
run. [...]
Here it explains,
i
is declared inside makeArmy
function's main body and thus it's scope is inside makeArmy
function.i
inside shooter function and hence,i
in shooter function is taken from its outer lexical environment.tl;dr - whenever a shooter function is called, value of i
is taken from its outer lexical environment.
From solution:
[...] But when
army[5]()
is called,makeArmy
has already finished its job, andi
has the last value: 10 (the end of while).As a result, all shooter functions get from the outer lexical environment the same, last value
i=10
.
This explains that
at the end of while loop in makeArmy
function,i
has the value 10
and hence,
at the end of makeArmy
function, i
has value 10
.
makeArmy
function's lexical environment has a variable named i
with value 10
whenever any of the functions in army
array is called, value of i
is taken from shooter function's outer lexical environment. It looks something like this
army[5]()
alert(i)
->
i
->
i
->
makeArmy
function's lexical environment -> found variable named i
with value 10
10
Important: This is just for the sake of explaining. This is NOT how it is actually done!
While loop solution:
function makeArmy() {
let shooters = [];
let i = 0;
while (i < 10) {
let j = i;
let shooter = function() { // shooter function
alert( j ); // should show its number
};
shooters.push(shooter);
i++;
}
return shooters;
}
let army = makeArmy();
Here, variable i
's value is assigned to j
and show alert with j
.
army[5]()
alert(j)
->j
->
j
with value 5
(see below)5
What happens in the first case is that there is no variable i
in while loop. So on each iteration, while loop create a new lexical environment and put something like this --
there is nothing here. you might find what you are looking for in
makeArmy()
's lexical environment
That's why, all footer functions show an alert with 10
.
In second case, while loop's lexical environment is --
j=<current_value>
. if that's not what you're looking for, you might find it inmakeArmy()
's lexical environment
See https://javascript.info/task/make-army/lexenv-makearmy.svg. So it shows alert with values we expect!
Important: This is just for the sake of explaining. This is NOT how it is actually done!
Parts that made me mostly confused for the first time:
Now it works correctly, because every time the code block in
for (let i=0...) {...}
is executed, a new Lexical Environment is created for it, with the corresponding variablei
.The
while
loop, just likefor
, makes a new Lexical Environment for each run. So here we make sure that it gets the right value for a shooter.
You are right! This part can be interpreted in a different way. Some restructuring is needed. Maybe swapping for
solution and it's description with while
solution? After all, while
is used in task.
@iliakan : I think an explanation of for
inline variable declaration's binding when using var
and let
is necessary. https://2ality.com/2015/02/es6-scoping.html#let-in-loop-heads
The information is there, but let's try to improve the text =)
Could you suggest a PR please?
I'll try!
P.S. Are you okay swapping for
with while
?
@MuhammedZakir Go try mate. You seem to know Javascript better than me. I suggest not adding too much extra words. Just try to rephrase some of the text and clear the possible misleading part.
@ajfg93 : What do you think?
Edit: This maybe interesting to you -- https://www.ecma-international.org/ecma-262/6.0/#sec-blockdeclarationinstantiation.
@MuhammedZakir Maybe you don't want to introduce for
loop about this solution. Here is a good video: JavaScript for-loops are… complicated - HTTP203 - YouTube
All the point is let in the initializer of for loop does have its own special and complicated runtime semantics.
Here is spec: https://www.ecma-international.org/ecma-262/6.0/#sec-for-statement-runtime-semantics-labelledevaluation
You should know this chapter is in advanced section and almost all chapters use let
for variable declaration. So I guess it's fine to put for
solution here. However, I think we should have a section about using var
vs let
as for
inline-variable declaration. @iliakan: if there is an explanation about it, where exactly is it? If it is explained before this chapter, then it's even more okay! If it is after this chapter, then either put a note or remove it(?). If there is no such explanation anywhere, we can decide whether to remove it or not after deciding where to put that explanation.
@xxleyi: Any input?
[...] Here is a good video: JavaScript for-loops are… complicated - HTTP203 - YouTube
Thanks for sharing this! 👍 FYI, I just tested the last code in this video in Chrome, Firefox & Safari and found out that each of them handle it differently! 😪
@iliakan : I couldn't extract strings from the image I created. How should I fix it? I am not familiar with SVG.
Have you created a new image from scratch?
Have you created a new image from scratch?
Yes!
@MuhammedZakir I tested too, Safari 12 is 1, Firefox 68 and Chrome 84 is 0. Maybe it's a bug in Safari 12 ?
And I found such explanation in https://javascript.info/closure
Now it works correctly, because every time the code block in
for (let i=0...) {...}
is executed, a new Lexical Environment is created for it, with the corresponding variablei
.
This explanation is good for practice, but is not very clear if we think more, the description the corresponding variable i
is vague.
Maybe this can be replaced with a more accurate explanation.
@MuhammedZakir I tested too, Safari 12 is 1, Firefox 68 and Chrome 84 is 0. Maybe it's a bug in Safari 12 ?
I guess so!
And I found such explanation in https://javascript.info/closure
Now it works correctly, because every time the code block in
for (let i=0...) {...}
is executed, a new Lexical Environment is created for it, with the corresponding variablei
.This explanation is good for practice, but is not very clear if we think more, the description the corresponding variable
i
is vague.Maybe this can be replaced with a more accurate explanation.
for (let i=0...) {...}
is executed, a new Lexical Environment is created for it, with variable i
, along with it's current value."i
, along with it's current value."i
and its value at the time of iteration."Have you created a new image from scratch?
@iliakan: FYI, I could't find a free SVG editor for Mac. I found a web app, but it wasn't easy. So I created it using 'drawio'. It's not an SVG editor, but can export to SVG. I will try to figure it out if you tell me what to do to make it right.
@MuhammedZakir maybe you just tell me what to change?
So that we won't spend time exploring this without a good reason =)
If you are talking about SVG, I honestly don't know! That was my first SVG! So I don't know what to do. There isn't any need for translation for the image I created for this chapter, but it would be helpful to know how to make my images compatible with your string extractor, in case, if I had to one that needs translation.
Also, if you are okay with the changes I made, shall I create a PR?
For translation purposes, you shouldn't create an SVG of your own.
Do you want to add an additional image or modify an existing one? Besides translation.
For translation purposes, you shouldn't create an SVG of your own.
Ok.
Do you want to add an additional image or modify an existing one? Besides translation.
For image, none! For solution, "the corresponding variable i
" part is the only thing left.
So there's no need to change SVG? Let me know if I need to do something about it.
About the text, yes, please make a PR.
So there's no need to change SVG? Let me know if I need to do something about it.
No. You may want to check it though.
About the text, yes, please make a PR.
Ok. I will do it later.
To check this SVG for what? Sorry, trying to understand.
To check this SVG for what? Sorry, trying to understand.
It's okay! :-) Like I said earlier, I could not extract strings from my image. That means, it can't be translate even if someone want to. So I wanted you to check that image to see if there is a need for translation or not. If there is no need, then everything is okay. Else, we will have to create a new image, so that the strings can be extracted for translation.
There is an "Army of functions" exercise in this chapter. And I suggest some modifications for the explanation/solution.
If I understand correctly, using
let
doesn't create a new Lexical Environment and it is the{}
block clause creates a new Lexical Environment each time andlet
just creates a local variable inside the Lexical Environment, whilevar
hoists the variable into the function level scope when creating a variable. So, whether usinglet
or not, there is a new Lexical Environment created each run infor(){}
orwhile{}
.But for the first time I read the solution/explanation, I thought it was using
let
that creates a new Lexical Environment. Kinda misleading until I read some thing on MDN aboutlet
.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
The quotes above did not direclty clear my doubt but made me thought twice. And then I got my coherent conclusion.
Parts that made me mostly confused for the first time:
And becasue you are adding a new
let
or replacingvar
withlet
in each new code snippet. So I was more likey to believe that it waslet
that somehow creates a new Lexical Environment.To sum up, I suggest making some modification here and let the readers know
let
does not create a new Lexical Environment, while{}
does.Anyway, it's just my opinion. (Or my conclusion could totally be wrong. I write
C++
most of my times.)--
In the end, I would like to thank you so much for the tutorial. It's so far the best I could find in the Net. So much better than the classic book I've read. I am going to buy a full tutorial.