Reputation: 146
Please explain the difference between Both codes. Why Outputs of both are different.
'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
'use strict';
let printNumTwo;
let i;
for (i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
Upvotes: 0
Views: 208
Reputation: 45121
The difference is in the scope where i
was declared.
Declares i
inside for loop block scope
'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) { // block scope
// each time we have new variable i
if (i === 2) { // block scope
printNumTwo = function() {
return i; // captures the one that was equal 2
};
}
}
// console.log(i) // throws ReferenceError
console.log(printNumTwo());
Declares i
in global scope
'use strict';
let printNumTwo;
let i; // globally scoped
for (i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i; // captures globally scoped i which will be mutated i++
};
}
}
console.log(i) // prints 3
console.log(printNumTwo());
UPD Some docs Spec
13.7.4.8 Runtime Semantics:
ForBodyEvaluation ( test, increment, stmt, perIterationBindings, labelSet )
The abstract operation ForBodyEvaluation with arguments test, increment, stmt, perIterationBindings, and labelSet is performed as follows:
- Let
V
beundefined
.- Perform ?
CreatePerIterationEnvironment(perIterationBindings)
.- Repeat,
...
e. Perform ?
CreatePerIterationEnvironment(perIterationBindings)
.f. If
increment
is not [empty], then ...
Basically new PerIterationEnvironment
is created before increment
part. So function will capture i === 2
.
Upvotes: 3
Reputation: 3265
I will explain only the first example because the second is obvious
'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) { // block scope
printNumTwo = function() {
return i;
};
}
}
console.log(i)
console.log(printNumTwo());
when you use let inside for loop, it means that the variable i is only defined in the for scope, so in that scope when i is equal to 2 we set the variable printNumTwo, when we do i++ again, i change its value to 3 but it does not change its value inside the for scope, it remains equal to 2, which means if somehow if you wanna access the i value, it is always equal to 2
for (let i = 0; i < 3; i++) {
console.log(i) // prints 0,1,2
}
console.log(i) // undefined
The thing to remember is, even if when i is equal to 2 and we do i++, it does not change its value inside the for scope because i is defined with let
Upvotes: 1