Prakhar Agrawal
Prakhar Agrawal

Reputation: 146

let keyword in ES6

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

Answers (2)

Yury Tarabanko
Yury Tarabanko

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:

  1. Let V be undefined.
  2. Perform ? CreatePerIterationEnvironment(perIterationBindings).
  3. 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

Mehdi Souregi
Mehdi Souregi

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

Related Questions