3

The let statement is advocated for usage in for loops as replacement for var declaration of the iteration variable.

By using let the user can forgo the usage of immediate invocation function to preserve the value of iteration variable for callbacks for instance.

From mdn:

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);
}

// to achieve the same effect with 'var'
// you have to create a different context
// using a closure to preserve the value
for (var i = 1; i <= 5; i++) {
  var item = document.createElement('li');
  item.appendChild(document.createTextNode('Item ' + i));

    (function(i){
        item.onclick = function(ev) {
            console.log('Item ' + i + ' is clicked.');
        };
    })(i);
  list.appendChild(item);
}

If I update the iteration variable i at the end of the loop, the for structure will pick it up and use the new value in the comperator logic of the loop and transfer that value to the next execution of the block.

console.log("start");
for (let i = 0; i < 5; i++) {
    console.log("in loop", i);
    setTimeout(function () {           
      console.log(i);
    }, 0);
    i = i + 2;

}
console.log("end");

Results:

start
in loop 0
in loop 3
end
undefined
2
5

The changes in the second iteration, do not propagate to the first iteration timeout callback.

Currently I thing the for loop implementation create a block execution context for each iteration, transfer the iteration variable as param, and specifically extract its value after the execution of the block ends and use it in the for mechanism for the next iteration. But it would be interesting to know if this is true, or not, and how it is implemented.

elpddev
  • 4,314
  • 4
  • 26
  • 47
  • True. Depends on the browser – Jonas Wilms Jun 14 '17 at 12:57
  • 1
    Youll find how it works here https://www.ecma-international.org/ecma-262/7.0/index.html#sec-for-statement however, its not that readable... – Jonas Wilms Jun 14 '17 at 13:02
  • 1
    Have a look at https://www.ecma-international.org/ecma-262/7.0/index.html#sec-forbodyevaluation and the following paragraph. How it is implemented depends on the JavaScript engine. – Felix Kling Jun 14 '17 at 13:29

1 Answers1

1

There is not much to say. Your observation is correct. There is a separate block for each iteration. So, no matter how long your timeout is, you will always see the same result.

At the end of each iteration the value of i will be passed to the next iteration. Since i is not an object, it will not be passed by reference. Thus a modification/incrementation of i in the next iteration won't affect the value of i in the block of the previous iteration.

Just for fun, try using an object instead of a primitive number:

console.log("start");
for (let i = {i:0}; i.i < 5; i.i++) {
    console.log("in loop", i.i);
    setTimeout(function () {           
      console.log(i.i);
    }, 0);
    i.i = i.i + 2;

}
console.log("end");

Results:

start
in loop 0
in loop 3
end
undefined
6
6

As you can see, in that case your i.i variable will actually be passed by reference and thus you can modify it over different iteration blocks.

Forivin
  • 14,780
  • 27
  • 106
  • 199
  • *"Since i is not an object, it will not be passed by reference."* It's a common mistake to misuse the term "pass-by-reference". *Nothing* is pass-by-reference in JavaScript. Whether something is "pass-by-reference" or "pass-by-value" has nothing to do with the value that is passed. JavaScript is pass-by-value and objects are *represented as* references. More: https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference – Felix Kling Jun 14 '17 at 13:31
  • I see what you mean. Any suggestions on how to rephrase it? – Forivin Jun 14 '17 at 13:38
  • "Since the value of `i` is a number and therefore immutable" maybe. – Felix Kling Jun 14 '17 at 13:47