Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ECMAScript 2015: const in for loops

Which of the two (or neither/ both) code fragments below should be working in a complete ECMAScript 2015 implementation:

for (const e of a)

for (const i = 0; i < a.length; i += 1)

From my understanding, the first example should work because e is initialized for each iteration. Shouldn't this also be the case for i in the second version?

I'm confused because existing implementations (Babel, IE, Firefox, Chrome, ESLint) do not seem to be consistent and have a complete implementation of const, with various behaviours of the two loop variants; I'm also not able to find a concrete point in the standard, so that would be much appreciated.

like image 465
adrianp Avatar asked Aug 13 '15 11:08

adrianp


People also ask

Can you use const in a for loop?

Use const if you want the identifier within the loop body to be read-only (so that, for instance, if someone modifies the code later to add an assignment, it's a proactive error).

Can we use const in for loop JavaScript?

for/in and for/of expose the same behavior for const and let , but the normal for loop does not. It explicitly treats const differently (understandably maybe). You simply say that it is "declared once" but that simplifies it too much IMO.

What is const [] in JS?

In JavaScript, `const` means that the identifier can't be reassigned. (Not to be confused with immutable values. Unlike true immutable datatypes such as those produced by Immutable. js and Mori, a `const` object can have properties mutated.)

Does const exist in ES5?

As we knew that 'let & const' are not coming in ES5, those are coming in ES6 since 2015. So to make these work like in latest version ECMA Scripts 2015, we can define it by ourself. actually 'let' in ES6 has function to make scope in javascript.


3 Answers

The following for-of loop works:

for (const e of a)

The ES6 specification describes this as:

ForDeclaration : LetOrConst ForBinding

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-in-and-for-of-statements-static-semantics-boundnames

The imperative for loop will not work:

for (const i = 0; i < a.length; i += 1)

This is because the declaration is only evaluated once before the loop body is executed.

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-statement-runtime-semantics-labelledevaluation

like image 59
lyschoening Avatar answered Oct 21 '22 22:10

lyschoening


I won't cite the spec this time, because I think it's easier to understand what happens by example.

for (const e of a) …

Is basically equivalent to

{
    const __it = a[Symbol.iterator]();
    let __res;
    while ((__res = __it.next()) && !__res.done) {
        const e = __res.value;
        …
    }
}

For simplicity I've ignored that there's a TDZ with e for the a expression, and the various __it.return()/__it.throw(e) calls in the case the loop exits prematurely (break or throw in the body).

for (const i = 0; i < a.length; i += 1) …

is basically equivalent to

{
    const i = 0;
    while (i < a.length) {
        …
        i += 1;
    }
}

In contrast to let, a const declaration in a for loop does not get redeclared in every loop iteration (and the initialiser is not re-executed anyway). Unless you break in the first iteration, your i += will throw here.

like image 35
Bergi Avatar answered Oct 21 '22 22:10

Bergi


Your second example should definitely not work because i is declared once and not on each iteration this is just a function of how that category of loops work.

You can try this in a regular browser:

for (var i = 0, otherVar = ""; i < [1,2,3,4].length; i += 1){
  console.log(otherVar)
  otherVar = "If otherVar was initialized on each iteration, then you would never read me.";
}

It's not the case that const is entirely disallowed in for loops. Only for that will modify const is.

These are valid:

for(const i = 0;;){ break } 
for(const i = 0; i < 10;){ break; } 

These are invalid:

for(const i = 0;;){ ++i; break; } 
for(const i = 0;;++i){ if(i > 0) break; }

I'm not sure why Firefox gives a SyntaxError after reading the ES2015 spec (although I'm sure the clever folk at Mozilla are correct), it seems like it's supposed to raise an exception:

Create a new but uninitialized immutable binding in an Environment Record. The String value N is the text of the bound name. If S is true then attempts to access the value of the binding before it is initialized or set it after it has been initialized will always throw an exception, regardless of the strict mode setting of operations that reference that binding. S is an optional parameter that defaults to false.

like image 6
Kit Sunde Avatar answered Oct 21 '22 21:10

Kit Sunde