How variables defined with `let` act inside a` for` loop

The documentation for the let statement in MDN has the following example:

 var list = document.getElementById("list"); for (let i = 1; i <= 5; i++) { let item = document.createElement("li"); item.appendChild(document.createTextNode("Item " + i)); item.onclick = function (ev) { console.log("Item " + i + " is clicked."); }; list.appendChild(item); } 

Then they declare:

The above example works as intended, since five instances of the (anonymous) inner function refers to five different instances of the variable i .

I don’t understand why there are β€œfive different instances of variable i .

The first statement in a for loop always executes once, no? Thus, the let statement should be executed only once ... As soon as the code reaches the end of the iteration, it checks the condition in the second expression.

Why, according to what they write, is there a new instance of i at each iteration?

+5
source share
2 answers

When using the let expression, each iteration creates a new lexical region bound to the previous region.

This means that each closure captures a different instance.

This complies with the ECMA 6 specification , but is not sure that it will work the same in all browsers.

Also not sure about performance. I would prefer to use this feature.

+3
source

In Javascript, variables are traditionally functional . Blocks, such as ... for loop statements, do not create a new area.

If you declare a variable with var at any point in your function (for example, in a for loop), it will be declared only once at the top of the scope thanks to hoisting , and there will be only one instance in the scope of the entire function.

This can lead to problems when calling callbacks inside a for ... loop.

 // with hoisting, i is only declared once for (var i in items) { // the fn is called items.length times, before any callback is invoked _fetchItems(items[i], function() { console.log("fetched for ", items{i]); // for all callbacks, i is the same value items.length-1 // because they are called after the loop is complete }); } 

Or in your example:

 // with hoisting, i is only declared once for (var i = 1; i <= 5; i++) { // with hoisting, item is only declared once var item = document.createElement("li"); item.appendChild(document.createTextNode("Item " + i)); // this function will be called after the for...loop is complete // so i value is unique: 5 + 1 = 6 item.onclick = function (ev) { // => always return "Item 6 is clicked" console.log("Item " + i + " is clicked."); }; list.appendChild(item); } 

Conversely, let variables are only bound to the closest block (i.e., any section of code between curly braces).

In your example, a new instance of the variable i declared for each execution of the block inside the for .... loop. i goes from 1 to 5, so there are 5 executions of the block, therefore, 5 instances of the variable.

Each of them will return the expected value "Click on element 1.", "Click on element 2", etc.

0
source

All Articles