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

In this case, var used.

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

In this case, let used.

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

I do not understand why the result is different. Can anybody help me?

+6
source share
4 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 a 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 being logged.

let (ECMAScript 6)

Here i is a local variable whose scope is limited by the for statement. Moreover, this variable gets a new binding at each iteration. This is best explained by your code translated into 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, at the seventh iteration, for example, the value of i will be 6 (from scratch). A function created inside an iteration will refer to this value.

+5
source

I think it would be much better not to define functions in a loop, you could easily accomplish this with a single function definition that returns 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, let used to determine the scale of the block. The best 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 

Change As I said in my commentary on your question, this is more likely a side effect of the transpilator you are using. Firefox supports block overviews, and both versions of your loop produce 10 as output (what they need).

+2
source

This is the correct behavior as per specification. The behavior with var and let is defined as different.

See the specification at https://people.mozilla.org/~jorendorff/es6-draft.html#sec-forbodyevaluation . Accordingly, the relevant concepts that make a function declared inside a loop closed at the current value of the loop index with a limited block are called “bindings for each iteration” and “environment for each iteration”.

Babel processes it correctly, generating the following code:

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

This implements the semantics of for (let , isolating the contents of the for loop in a separate function parameterized by the index. Therefore, the function no longer closes by the index of the for loop, and i processed separately in each created function. Thus, the answer is 6.

Traceur does not give the correct result. This gives 10.

So, the famous question that was asked 100 times on SO about why my function declared in the loop and closing the index index using the "wrong" value of the loop index is no longer being requested?

The question is a little more nuanced, which simply proclaims that "of course let is a block area." We know that. For example, we get how it works in the if block. But what happens here is a bit of a twist on block coverage in a for context hitherto unknown to many people, including me. This is a variable that actually declared outside the "block" (if you consider the block as the body of the for statement), but has a separate existence inside , each iteration of the loop.

See https://github.com/babel/babel/issues/1078 for more details.

+2
source

Why is the result different from ES6 and ES5?

Because let and var are different. let with block scope , and var with functionality .

In your first example, there is only one variable i . Each function you create refers to the same variable i . You are currently calling a[6]() , i has a value of 10 because this is a termination condition for a loop.

In the second example, each iteration of the loop has its own variable i . It works in exactly the same way as in other languages ​​with block volume.

+1
source

Source: https://habr.com/ru/post/987633/


All Articles