Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is result different (using var vs. let)?

This uses var

var a = [];
for (var i = 0; i < 10; i++) {
    a[i] = function() {
        console.log(i);
    };
}
a[6](); // 10

This uses let

var a = [];
for (let i = 0; i < 10; i++) {
    a[i] = function() {
        console.log(i);
    };
}
a[6](); // 6

I don't understand why the result is different. Can somebody guide me?

like image 863
dukegod Avatar asked May 21 '15 06:05

dukegod


People also ask

Is it better to use let or VAR?

This is because both instances are treated as different variables since they have different scopes. This fact makes let a better choice than var . When using let , you don't have to bother if you have used a name for a variable before as a variable exists only within its scope.

Why is let better than VAR?

let allows you to declare variables that are limited to the scope of a block statement, or expression on which it is used, unlike the var keyword, which declares a variable globally, or locally to an entire function regardless of block scope.

What is the difference between VAR and let in terms of performance?

In terms of performance comparison, var is faster and let is slower inside the loops while running or executing the code. Re-declaring var declared a variable in the same function or scope gives rise to Syntax Error whereas let declared variable cannot be redeclared.

Is there any reason to use var over Let?

let is preferable to var because it reduces the scope in which an identifier is visible. It allows us to safely declare variables at the site of first use. const is preferable to let . Unless you need to mutate a reference, use a const declaration.


2 Answers

The resulting array consists of functions, each function body looks like this:

console.log(i);

The value of i depends on whether we used var or let to declare the variable.

var (ECMAScript 5 and 6)

Here i is a global variable whose value is 10 after exiting the loop. This is the value that is logged.

let (ECMAScript 6)

Here i is a local variable whose scope is restricted to the for statement. Moreover, this variable gets a fresh binding on each iteration. This is best explained by your code transpiled to ECMAScript 5:

"use strict";
var a = [];
var _loop = function(i) {
    a[i] = function() {
        console.log(i);
    };
};
for (var i = 0; i < 10; i++) {
    _loop(i);
}
a[6](); // 6

So, on seventh iteration for example, the value of i will be 6 (counting from zero). The function created inside the iteration will refer to this value.

like image 174
Salman A Avatar answered Oct 05 '22 20:10

Salman A


I think it would be much better to not define functions in a loop, you could easily accomplish this with one function definition that returns a closure:

function logNumber(num) {
   return function() {
     console.log(num);
   }
}

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = logNumber(i);
}
a[6]();

Regarding the difference between the two examples, one is using let for block scoping. A better example that shows the difference would be:

ECMA5:

for (var i = 0; i < 10; i++) { }
console.log(i); // 10

ECMA6:

for (let i = 0; i < 10; i++) { }
console.log(i); // i is not defined

Edit: as I stated in my comment to your question, this is more likely a side-effect of the transpiler you are using. Firefox supports block scoping and both versions of your loop produce 10 as output (which they should).

like image 31
Rob M. Avatar answered Oct 05 '22 21:10

Rob M.