So I noticed that I have to use let inside a for loop, and cannot use const. However, I found that I can use const inside the for-in and for-of constructs (code below). Intuitively I can rationalize that this is because the for loop is implemented differently/is more primitive, whereas the other constructs desugar into for loops where the iterating variable is assigned at the top of the for loop.
// Doesn't work
for (const i = 0; i < 3; i++) {
console.log(i);
}
// Works
for (let i = 0; i < 3; i++) {
console.log(i);
}
// Works
const object2 = ['a', 'b', 'c'];
for (const v of object2) {
console.log(v);
}
// Works
const object3 = {
a: 'a',
b: 'b',
c: 'c',
};
for (const v in object3) {
console.log(v);
}
The only thing I could find on Mozilla MDN about this was on the for loop page:
This expression may optionally declare new variables with the var keyword. These variables are not local to the loop, i.e. they are in the same scope the for loop is in. The result of this expression is discarded.
Which also seems wrong, because if we use a let for i then i is no longer in scope after the for loop (which is consistent with other languages)
for (let i = 0; i < 3; i++) {
console.log(i);
}
// Doesn't work as expected
console.log(i);
My question is whether this behaviour is expected and defined in the spec somewhere? MDN doesn't say much about this.
Yes. This is indeed expected behavior.
const defines a variable which, as the name suggested, stays constant. That means the value of a const cannot change.
Now what you do in your for loop is incrementing "i", which was defined as a constant.
for (const i = 0; i < 3; i++ /* <- this doesn't work */ ) {
console.log(i);
}
with for .. in or for .. of however, you just bind the variable.
In other words: With for .. in/off, the variable gets assigned once before execution of the loop and not on every iteration. Therefore const can indeed be used.
As for the reference:
ForDeclaration : LetOrConst ForBinding
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-in-and-for-of-statements-static-semantics-boundnames
So I noticed that I have to use let inside a for loop, and cannot use const.
No. You can use a const declaration in a for loop just fine. The problem just is that const declares a constant binding, so an increment i++ doesn't work on const i (it should throw an exception, make sure you're in strict mode).
An example of how to use const:
for (const o = {index: 0, value: null}; o.index < arr.length; o.index++) {
o.value = arr[o.index];
doSomething(o);
}
Or one where it makes more sense:
for (const iterator = makeIterator(); !iterator.isDone(); iterator.next())
doSomething(iterator.getCurrent());
}
Intuitively I can rationalize that this is because the for loop is implemented differently/is more primitive, whereas the other constructs desugar into for loops where the iterating variable is assigned at the top of the for loop.
Yes. In a for loop, you need to take care of updating the iteration variables yourself.
for ([var] init; condition; update) {
body
}
becomes
[var] init;
while (condition) {
body;
update;
}for (const init; condition; update) {
body
}
becomes
{
const init;
while (condition) {
body;
update;
}
}for (let init; condition; update) {
body
}
becomes something more complicated
In for … in and for … of loops, you just declare an assignment target expression for the produced value.
for ([var]/let/const target of iterable) {
body
}
becomes
{
const _iterator = iterable[Symbol.iterator]();
let _result;
while (!(_result = _iterator.next()).done) {
[var]/let/const target = _result.value;
body;
}
}for (… in enumerable) is just the same as for (… of Reflect.enumerate(enumerable)).
The only thing I could find on Mozilla MDN about this was on the
forloop page, which also seems wrong.
Yes, looks like that section hasn't yet been updated for ES6.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With