Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

77%
+5 −0
Q&A Does a for...of loop must contain a variable without assignment sign, and why?

Does a for...of loop must contain a variable without assignment sign (=) Yes. and why? Because that's the syntax defined by the language specification. The people who defined it decided ...

posted 2y ago by hkotsubo‭  ·  edited 2y ago by hkotsubo‭

Answer
#3: Post edited by user avatar hkotsubo‭ · 2022-04-28T18:27:07Z (almost 2 years ago)
  • > *Does a `for...of` loop must contain a variable without assignment sign (`=`)*
  • Yes.
  • > *and why?*
  • Because that's the syntax [defined by the language specification](https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-for-in-and-for-of-statements). The people who defined it decided to do it that way.
  • Unless those people answer here (or we find a discussion about it somewhere, which I couldn't), we can only speculate why they have chosen this particular syntax instead of any other one.
  • [In the comments](https://software.codidact.com/comments/thread/6181#comment-17211), there's one argument against having a `=`: it would be confusing to have code like `for (const variable = collection)`, because it looks like the whole `collection` is being assigned to `variable`. By making it `for (const variable of collection)`, it avoids this confusion and makes it more clear that the variable is iterating through the `collection`'s elements.
  • Of course this is debatable and each one will have their opinion about this being more clear or confusing. When I learned `for..of`, I was already familiar with similar constructs from another languages, so it wasn't confusing to me. But YMMV, as always.
  • I'd like to add that other languages have similar loops:
  • - Java has the enhanced-for loop: `for (Type variable : collection)`
  • - C# has the `foreach` loop: `foreach (Type variable in collection)`
  • - Python uses a `for..in` loop: `for variable in collection`
  • - PHP has the `foreach` loop, but the variable comes after the collection: `foreach ($collection as $variable)`
  • And so on. Just for the record, JavaScript also has `for..in` loops, with a similar syntax (`for (const variable in collection)`), but [**different behaviour**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of#difference_between_for...of_and_for...in).
  • Anyway, each language chooses whatever syntax they want to. The people who defines it might consider many factors to decide between one or another, and each language also has their own processes to discuss and decide it (such as [PEP's for Python](https://peps.python.org/), [JEP's for Java](http://openjdk.java.net/jeps/1), [TC39 for JS](https://github.com/tc39/proposals), etc). Sometimes the decision has a reasonable rationale, technical justifications, etc, but sometimes is just a matter of personal preference (I can't tell which one drove the decision of the `for..of` syntax, though).
  • Therefore, IMO the only reasonable answer to "_Why does a `for..of` loop requires a specific syntax?_" is simply "_Because it was defined that way_". To know why it was decided to use syntax A instead of B, we should ask to the people who made the decision (without that, the best we can do is only speculate).
  • ---
  • > *Is there a way to achieve the same result with "regular" variable declaration?*
  • Maybe, it depends on what the code does.
  • For a simple loop such as:
  • ```javascript
  • const collection = [ 1, 2, 3, 4, 5 ];
  • for (const variable of collection) {
  • console.log(variable);
  • }
  • ```
  • You could declare the variable outside the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • console.log(variable);
  • }
  • ```
  • **Although the "result" (AKA the output) is the same, there are some differences.**
  • I can't use `const` in the second case, because the `variable` will be assigned a different value in each iteration.
  • And by not using `const`, this means that I could change its value inside the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • variable = 1000;
  • console.log(variable);
  • }
  • ```
  • If I use `const` and declare it inside the loop, though, I can't change its value:
  • ```javascript
  • for (const variable of collection) {
  • variable = 1000; // error!
  • console.log(variable);
  • }
  • ```
  • This gives me an error because [I can't assign another value to a `const` variable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const). That's useful if you want to make sure that the `variable` isn't changed inside the loop.
  • Another difference is that in the second code, the `variable` still exists after the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • console.log(variable);
  • }
  • console.log('after', variable); // variable has the value of the last collection's element
  • ```
  • That's because it was declared outside the loop.
  • But if I do this:
  • ```javascript
  • for (const variable of collection) {
  • console.log(variable);
  • }
  • console.log('after', variable); // error (variable is out of scope and doesn't exist outside the loop)
  • ```
  • Now the `variable`'s scope is the `for..of` loop, thus it can't be accessed outside the loop. That's useful to limit the variable's scope.
  • ---
  • Of course you could also use a "traditional" `for`:
  • ```javascript
  • for (let i = 0; i < collection.length; i++) {
  • const variable = collection[i];
  • console.log(variable);
  • }
  • ```
  • But the `for..of` loop is actually more than just an alternative syntax, because it allows you to loop through any iterable object.
  • Not all iterable objects have the `length` property, and some might not support the `[]` syntax to access a specific element. For those objects, the `for..of` loop provides a standard way to loop through them, all they have to do is implement the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol).
  • Just to provide some examples:
  • ```javascript
  • // A Set doesn't have a way to access individual elements by index
  • var set = new Set([1, 2, 3, 1, 4, 5]);
  • for (const n of set) {
  • console.log(n);
  • }
  • // I can iterate through the keys and respective values of a Map
  • var map = new Map([ ['name', 'Douglas'], ['age', 42], ['country', 'UK']]);
  • // and I can also use destructuring assignment: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
  • for (const [key, value] of map.entries()) {
  • console.log(`${key} = ${value}`);
  • }
  • ```
  • ---
  • And there are cases where the results are different, such as when looping through the characters of a string:
  • ```javascript
  • const string = 'abc' + String.fromCodePoint(0x1F60A);
  • for (const character of string) {
  • console.log(character);
  • }
  • ```
  • The output is (note the emoji in the end):
  • ```none
  • a
  • b
  • c
  • 😊
  • ```
  • But with a traditional `for`:
  • ```javascript
  • for (let i = 0; i < string.length; i++) {
  • console.log(string[i]);
  • }
  • ```
  • This will print:
  • ```none
  • a
  • b
  • c
  • ```
  • That's because `for..of` loops through the Unicode code points, while the traditional loop breaks some of them in surrogate pairs. I know that's *way* beside the point, it was just to show that a `for..of` loop has its own characteristics, and sometimes there's no obvious equivalent using other types of loops (but if you're curious about all this Unicode stuff, take a look at [this answer](https://software.codidact.com/posts/283000/283058#answer-283058)).
  • ---
  • # Summary
  • - the `for..of` loop syntax is the way it is, because whoever designed it, decided it that way
  • - some cases might be interchangeable with a traditional `for` loop, some other cases might not
  • > *Does a `for...of` loop must contain a variable without assignment sign (`=`)*
  • Yes.
  • > *and why?*
  • Because that's the syntax [defined by the language specification](https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-for-in-and-for-of-statements). The people who defined it decided to do it that way.
  • Unless those people answer here (or we find a discussion about it somewhere, which I couldn't), we can only speculate why they have chosen this particular syntax instead of any other one.
  • [In the comments](https://software.codidact.com/comments/thread/6181#comment-17211), there's one argument against having a `=`: it would be confusing to have code like `for (const variable = collection)`, because it looks like the whole `collection` is being assigned to `variable`. By making it `for (const variable of collection)`, it avoids this confusion and makes it more clear that the variable is iterating through the `collection`'s elements.
  • > Of course this is debatable and each one will have their opinion about this being more clear or confusing. When I learned `for..of`, I was already familiar with similar constructs from another languages, so it wasn't confusing to me. But YMMV, as always.
  • I'd like to add that other languages have similar loops:
  • - Java has the enhanced-for loop: `for (Type variable : collection)`
  • - C# has the `foreach` loop: `foreach (Type variable in collection)`
  • - Python uses a `for..in` loop: `for variable in collection`
  • - PHP has the `foreach` loop, but the variable comes *after* the collection: `foreach ($collection as $variable)`
  • - D also has `foreach`, but with a different syntax: `foreach (variable; collection)`
  • And so on, the list of syntax variations among different languages is [huge](https://en.wikipedia.org/wiki/Foreach_loop#Language_support). Just for the record, JavaScript also has `for..in` loops, with a similar syntax (`for (const variable in collection)`), but [**different behaviour**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of#difference_between_for...of_and_for...in).
  • Anyway, each language chooses whatever syntax they want to. The people who defines it might consider many factors to decide between one or another, and each language also has their own processes to discuss and decide it (such as [PEP's for Python](https://peps.python.org/), [JEP's for Java](http://openjdk.java.net/jeps/1), [TC39 for JS](https://github.com/tc39/proposals), etc). Sometimes the decision has a reasonable rationale, technical justifications, etc, but sometimes is just a matter of personal preference (I can't tell which one drove the decision of the `for..of` syntax, though).
  • Therefore, IMO the only reasonable answer to "_Why does a `for..of` loop requires a specific syntax?_" is simply "_Because it was defined that way_". To know why it was decided to use syntax A instead of B, we should ask to the people who made the decision (without that, the best we can do is only speculate).
  • ---
  • > *Is there a way to achieve the same result with "regular" variable declaration?*
  • Maybe, it depends on what the code does.
  • For a simple loop such as:
  • ```javascript
  • const collection = [ 1, 2, 3, 4, 5 ];
  • for (const variable of collection) {
  • console.log(variable);
  • }
  • ```
  • You could declare the variable outside the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • console.log(variable);
  • }
  • ```
  • **Although the "result" (AKA the output) is the same, there are some differences.**
  • I can't use `const` in the second case, because the `variable` will be assigned a different value in each iteration.
  • And by not using `const`, this means that I could change its value inside the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • variable = 1000;
  • console.log(variable);
  • }
  • ```
  • If I use `const` and declare it inside the loop, though, I can't change its value:
  • ```javascript
  • for (const variable of collection) {
  • variable = 1000; // error!
  • console.log(variable);
  • }
  • ```
  • This gives me an error because [I can't assign another value to a `const` variable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const). That's useful if you want to make sure that the `variable` isn't changed inside the loop.
  • Another difference is that in the second code, the `variable` still exists after the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • console.log(variable);
  • }
  • console.log('after', variable); // variable has the value of the last collection's element
  • ```
  • That's because it was declared outside the loop.
  • But if I do this:
  • ```javascript
  • for (const variable of collection) {
  • console.log(variable);
  • }
  • console.log('after', variable); // error (variable is out of scope and doesn't exist outside the loop)
  • ```
  • Now the `variable`'s scope is the `for..of` loop, thus it can't be accessed outside the loop. That's useful to limit the variable's scope.
  • ---
  • Of course you could also use a "traditional" `for`:
  • ```javascript
  • for (let i = 0; i < collection.length; i++) {
  • const variable = collection[i];
  • console.log(variable);
  • }
  • ```
  • But the `for..of` loop is actually more than just an alternative syntax, because it allows you to loop through any iterable object.
  • Not all iterable objects have the `length` property, and some might not support the `[]` syntax to access a specific element. For those objects, the `for..of` loop provides a standard way to loop through them, all they have to do is implement the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol).
  • Just to provide some examples:
  • ```javascript
  • // A Set doesn't have a way to access individual elements by index
  • var set = new Set([1, 2, 3, 1, 4, 5]);
  • for (const n of set) {
  • console.log(n);
  • }
  • // I can iterate through the keys and respective values of a Map
  • var map = new Map([ ['name', 'Douglas'], ['age', 42], ['country', 'UK']]);
  • // and I can also use destructuring assignment: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
  • for (const [key, value] of map.entries()) {
  • console.log(`${key} = ${value}`);
  • }
  • ```
  • ---
  • And there are cases where the results are different, such as when looping through the characters of a string:
  • ```javascript
  • const string = 'abc' + String.fromCodePoint(0x1F60A);
  • for (const character of string) {
  • console.log(character);
  • }
  • ```
  • The output is (note the emoji in the end):
  • ```none
  • a
  • b
  • c
  • 😊
  • ```
  • But with a traditional `for`:
  • ```javascript
  • for (let i = 0; i < string.length; i++) {
  • console.log(string[i]);
  • }
  • ```
  • This will print:
  • ```none
  • a
  • b
  • c
  • ```
  • That's because `for..of` loops through the Unicode code points, while the traditional loop breaks some of them in surrogate pairs. I know that's *way* beside the point, it was just to show that a `for..of` loop has its own characteristics, and sometimes there's no obvious equivalent using other types of loops (but if you're curious about all this Unicode stuff, take a look at [this answer](https://software.codidact.com/posts/283000/283058#answer-283058)).
  • ---
  • # Summary
  • - the `for..of` loop syntax is the way it is, because whoever designed it, decided it that way
  • - some cases might be interchangeable with a traditional `for` loop, some other cases might not
#2: Post edited by user avatar hkotsubo‭ · 2022-04-28T14:23:33Z (almost 2 years ago)
  • > *Does a `for...of` loop must contain a variable without assignment sign (`=`)*
  • Yes.
  • > *and why?*
  • Because that's the syntax [defined by the language specification](https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-for-in-and-for-of-statements). The people who defined it decided to do it that way.
  • Unless those people answer here (or we find a discussion about it somewhere, which I couldn't), we can only speculate why they have chosen this particular syntax instead of any other one.
  • [In the comments](https://software.codidact.com/comments/thread/6181#comment-17211), there's one argument against having a `=`: it would be confusing to have code like `for (const variable = collection)`, because it looks like the whole `collection` is being assigned to `variable`. By making it `for (const variable of collection)`, it avoids this confusion and makes it more clear that the variable is iterating through the `collection`'s elements.
  • Of course this is debatable and each one will have their opinion about this being more clear or confusing. When I learned `for..of`, I was already familiar with similar constructs from another languages, so it wasn't confusing to me. But YMMV, as always.
  • I'd like to add that other languages have similar loops:
  • - Java has the enhanced-for loop: `for (Type variable : collection)`
  • - C# has the `foreach` loop: `foreach (Type variable in collection)`
  • - Python uses a `for..in` loop: `for variable in collection`
  • - PHP has the `foreach` loop, but the variable comes after the collection: `foreach ($collection as $variable)`
  • And so on. Just for the record, JavaScript also has `for..in` loops, with a similar syntax (`for (const variable in collection)`), but [**different behaviour**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of#difference_between_for...of_and_for...in).
  • Anyway, each language chooses whatever syntax they want to. The people who defines it might consider many factors to decide between one or another, and each language also has their own processes to discuss and decide it (such as [PEP's for Python](https://peps.python.org/), [JEP's for Java](http://openjdk.java.net/jeps/1), [TC39 for JS](https://github.com/tc39/proposals), etc). Sometimes the decision has a reasonable rationale, technical justifications, etc, but sometimes is just a matter of personal preference (I can't tell which one drove the decision of the `for..of` syntax, though).
  • Therefore, IMO the only reasonable answer to "_Why does a `for..of` loop requires a specific syntax?_" is simply "_Because it was defined that way_". To know why it was decided to use syntax A instead of B, we should ask to the people who made the decision (without that, the best we can do is only speculate).
  • ---
  • > *Is there a way to achieve the same result with "regular" variable declaration?*
  • Maybe, it depends on what the code does.
  • For a simple loop such as:
  • ```javascript
  • const collection = [ 1, 2, 3, 4, 5 ];
  • for (const variable of collection) {
  • console.log(variable);
  • }
  • ```
  • You could declare the variable outside the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • console.log(variable);
  • }
  • ```
  • **Although the "result" (AKA the output) is the same, there are some differences.**
  • I can't use `const` in the second case, because the `variable` will be assigned a different value in each iteration.
  • And by not using `const`, this means that I could change its value inside the loop:
  • ```javascript
  • let variable = 1;
  • for (variable of collection) {
  • variable = 1000;
  • console.log(variable);
  • }
  • ```
  • If I use `const` and declare it inside the loop, though, I can't change its value:
  • ```javascript
  • for (const variable of collection) {
  • variable = 1000; // error!
  • console.log(variable);
  • }
  • ```
  • This gives me an error because [I can't assign another value to a `const` variable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const). That's useful if you want to make sure that the `variable` isn't changed inside the loop.
  • Another difference is that in the second code, the `variable` still exists after the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • console.log(variable);
  • }
  • console.log('after', variable); // variable has the value of the last collection's element
  • ```
  • That's because it was declared outside the loop.
  • But if I do this:
  • ```javascript
  • for (const variable of collection) {
  • console.log(variable);
  • }
  • console.log('after', variable); // error (variable is out of scope and doesn't exist outside the loop)
  • ```
  • Now the `variable`'s scope is the `for..of` loop, thus it can't be accessed outside the loop. That's useful to limit the variable's scope.
  • ---
  • Of course you could also use a "traditional" `for`:
  • ```javascript
  • for (let i = 0; i < collection.length; i++) {
  • const variable = collection[i];
  • console.log(variable);
  • }
  • ```
  • But the `for..of` loop is actually more than just an alternative syntax, because it allows you to loop through any iterable object.
  • Not all iterable objects have the `length` property, and some might not support the `[]` syntax to access a specific element. For those objects, the `for..of` loop provides a standard way to loop through them, all they have to do is implement the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol).
  • Just to provide some examples:
  • ```javascript
  • // A Set doesn't have a way to access individual elements by index
  • var set = new Set([1, 2, 3, 1, 4, 5]);
  • for (const n of set) {
  • console.log(n);
  • }
  • // I can iterate through the keys and respective values of a Map
  • var map = new Map([ ['name', 'Douglas'], ['age', 42], ['country', 'UK']]);
  • // and I can also use destructuring assignment: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
  • for (const [key, value] of map.entries()) {
  • console.log(`${key} = ${value}`);
  • }
  • ```
  • ---
  • And there are cases where the results are different, such as when looping through the characters of a string:
  • ```javascript
  • const string = 'abc' + String.fromCodePoint(0x1F60A);
  • for (const character of string) {
  • console.log(character);
  • }
  • ```
  • The output is (note the emoji in the end):
  • ```none
  • a
  • b
  • c
  • 😊
  • ```
  • But with a traditional `for`:
  • ```javascript
  • for (let i = 0; i < string.length; i++) {
  • console.log(string[i]);
  • }
  • ```
  • This will print:
  • ```none
  • a
  • b
  • c
  • ```
  • That's because `for..of` loops through the Unicode code points, while the traditional loop breaks some of them in surrogate pairs. I know that's *way* beside the point, it was just to show that a `for..of` loop has its own characteristics, and sometimes there's no obvious equivalent using other types of loops (but if you're curious about all this Unicode stuff, take a look at [this answer](https://software.codidact.com/posts/283000/283058#answer-283058)).
  • ---
  • # Summary
  • - the `for..of` loop syntax is the way it is, because whoever designed it, decided it that way
  • - some cases might be interchangeable with a traditional `for` loop, some other cases might not
  • > *Does a `for...of` loop must contain a variable without assignment sign (`=`)*
  • Yes.
  • > *and why?*
  • Because that's the syntax [defined by the language specification](https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-for-in-and-for-of-statements). The people who defined it decided to do it that way.
  • Unless those people answer here (or we find a discussion about it somewhere, which I couldn't), we can only speculate why they have chosen this particular syntax instead of any other one.
  • [In the comments](https://software.codidact.com/comments/thread/6181#comment-17211), there's one argument against having a `=`: it would be confusing to have code like `for (const variable = collection)`, because it looks like the whole `collection` is being assigned to `variable`. By making it `for (const variable of collection)`, it avoids this confusion and makes it more clear that the variable is iterating through the `collection`'s elements.
  • Of course this is debatable and each one will have their opinion about this being more clear or confusing. When I learned `for..of`, I was already familiar with similar constructs from another languages, so it wasn't confusing to me. But YMMV, as always.
  • I'd like to add that other languages have similar loops:
  • - Java has the enhanced-for loop: `for (Type variable : collection)`
  • - C# has the `foreach` loop: `foreach (Type variable in collection)`
  • - Python uses a `for..in` loop: `for variable in collection`
  • - PHP has the `foreach` loop, but the variable comes after the collection: `foreach ($collection as $variable)`
  • And so on. Just for the record, JavaScript also has `for..in` loops, with a similar syntax (`for (const variable in collection)`), but [**different behaviour**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of#difference_between_for...of_and_for...in).
  • Anyway, each language chooses whatever syntax they want to. The people who defines it might consider many factors to decide between one or another, and each language also has their own processes to discuss and decide it (such as [PEP's for Python](https://peps.python.org/), [JEP's for Java](http://openjdk.java.net/jeps/1), [TC39 for JS](https://github.com/tc39/proposals), etc). Sometimes the decision has a reasonable rationale, technical justifications, etc, but sometimes is just a matter of personal preference (I can't tell which one drove the decision of the `for..of` syntax, though).
  • Therefore, IMO the only reasonable answer to "_Why does a `for..of` loop requires a specific syntax?_" is simply "_Because it was defined that way_". To know why it was decided to use syntax A instead of B, we should ask to the people who made the decision (without that, the best we can do is only speculate).
  • ---
  • > *Is there a way to achieve the same result with "regular" variable declaration?*
  • Maybe, it depends on what the code does.
  • For a simple loop such as:
  • ```javascript
  • const collection = [ 1, 2, 3, 4, 5 ];
  • for (const variable of collection) {
  • console.log(variable);
  • }
  • ```
  • You could declare the variable outside the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • console.log(variable);
  • }
  • ```
  • **Although the "result" (AKA the output) is the same, there are some differences.**
  • I can't use `const` in the second case, because the `variable` will be assigned a different value in each iteration.
  • And by not using `const`, this means that I could change its value inside the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • variable = 1000;
  • console.log(variable);
  • }
  • ```
  • If I use `const` and declare it inside the loop, though, I can't change its value:
  • ```javascript
  • for (const variable of collection) {
  • variable = 1000; // error!
  • console.log(variable);
  • }
  • ```
  • This gives me an error because [I can't assign another value to a `const` variable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const). That's useful if you want to make sure that the `variable` isn't changed inside the loop.
  • Another difference is that in the second code, the `variable` still exists after the loop:
  • ```javascript
  • let variable;
  • for (variable of collection) {
  • console.log(variable);
  • }
  • console.log('after', variable); // variable has the value of the last collection's element
  • ```
  • That's because it was declared outside the loop.
  • But if I do this:
  • ```javascript
  • for (const variable of collection) {
  • console.log(variable);
  • }
  • console.log('after', variable); // error (variable is out of scope and doesn't exist outside the loop)
  • ```
  • Now the `variable`'s scope is the `for..of` loop, thus it can't be accessed outside the loop. That's useful to limit the variable's scope.
  • ---
  • Of course you could also use a "traditional" `for`:
  • ```javascript
  • for (let i = 0; i < collection.length; i++) {
  • const variable = collection[i];
  • console.log(variable);
  • }
  • ```
  • But the `for..of` loop is actually more than just an alternative syntax, because it allows you to loop through any iterable object.
  • Not all iterable objects have the `length` property, and some might not support the `[]` syntax to access a specific element. For those objects, the `for..of` loop provides a standard way to loop through them, all they have to do is implement the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol).
  • Just to provide some examples:
  • ```javascript
  • // A Set doesn't have a way to access individual elements by index
  • var set = new Set([1, 2, 3, 1, 4, 5]);
  • for (const n of set) {
  • console.log(n);
  • }
  • // I can iterate through the keys and respective values of a Map
  • var map = new Map([ ['name', 'Douglas'], ['age', 42], ['country', 'UK']]);
  • // and I can also use destructuring assignment: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
  • for (const [key, value] of map.entries()) {
  • console.log(`${key} = ${value}`);
  • }
  • ```
  • ---
  • And there are cases where the results are different, such as when looping through the characters of a string:
  • ```javascript
  • const string = 'abc' + String.fromCodePoint(0x1F60A);
  • for (const character of string) {
  • console.log(character);
  • }
  • ```
  • The output is (note the emoji in the end):
  • ```none
  • a
  • b
  • c
  • 😊
  • ```
  • But with a traditional `for`:
  • ```javascript
  • for (let i = 0; i < string.length; i++) {
  • console.log(string[i]);
  • }
  • ```
  • This will print:
  • ```none
  • a
  • b
  • c
  • ```
  • That's because `for..of` loops through the Unicode code points, while the traditional loop breaks some of them in surrogate pairs. I know that's *way* beside the point, it was just to show that a `for..of` loop has its own characteristics, and sometimes there's no obvious equivalent using other types of loops (but if you're curious about all this Unicode stuff, take a look at [this answer](https://software.codidact.com/posts/283000/283058#answer-283058)).
  • ---
  • # Summary
  • - the `for..of` loop syntax is the way it is, because whoever designed it, decided it that way
  • - some cases might be interchangeable with a traditional `for` loop, some other cases might not
#1: Initial revision by user avatar hkotsubo‭ · 2022-04-28T14:21:08Z (almost 2 years ago)
> *Does a `for...of` loop must contain a variable without assignment sign (`=`)*

Yes.

> *and why?*

Because that's the syntax [defined by the language specification](https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-for-in-and-for-of-statements). The people who defined it decided to do it that way.

Unless those people answer here (or we find a discussion about it somewhere, which I couldn't), we can only speculate why they have chosen this particular syntax instead of any other one.

[In the comments](https://software.codidact.com/comments/thread/6181#comment-17211), there's one argument against having a `=`: it would be confusing to have code like `for (const variable = collection)`, because it looks like the whole `collection` is being assigned to `variable`. By making it `for (const variable of collection)`, it avoids this confusion and makes it more clear that the variable is iterating through the `collection`'s elements.

Of course this is debatable and each one will have their opinion about this being more clear or confusing. When I learned `for..of`, I was already familiar with similar constructs from another languages, so it wasn't confusing to me. But YMMV, as always.

I'd like to add that other languages have similar loops:

- Java has the enhanced-for loop: `for (Type variable : collection)`
- C# has the `foreach` loop: `foreach (Type variable in collection)`
- Python uses a `for..in` loop: `for variable in collection`
- PHP has the `foreach` loop, but the variable comes after the collection: `foreach ($collection as $variable)`

And so on. Just for the record, JavaScript also has `for..in` loops, with a similar syntax (`for (const variable in collection)`), but [**different behaviour**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of#difference_between_for...of_and_for...in).

Anyway, each language chooses whatever syntax they want to. The people who defines it might consider many factors to decide between one or another, and each language also has their own processes to discuss and decide it (such as [PEP's for Python](https://peps.python.org/), [JEP's for Java](http://openjdk.java.net/jeps/1), [TC39 for JS](https://github.com/tc39/proposals), etc). Sometimes the decision has a reasonable rationale, technical justifications, etc, but sometimes is just a matter of personal preference (I can't tell which one drove the decision of the `for..of` syntax, though).

Therefore, IMO the only reasonable answer to "_Why does a `for..of` loop requires a specific syntax?_" is simply "_Because it was defined that way_". To know why it was decided to use syntax A instead of B, we should ask to the people who made the decision (without that, the best we can do is only speculate).

---

> *Is there a way to achieve the same result with "regular" variable declaration?*

Maybe, it depends on what the code does.

For a simple loop such as:

```javascript
const collection = [ 1, 2, 3, 4, 5 ];
for (const variable of collection) {
    console.log(variable);
}
```

You could declare the variable outside the loop:

```javascript
let variable;
for (variable of collection) {
    console.log(variable);
}
```

**Although the "result" (AKA the output) is the same, there are some differences.**

I can't use `const` in the second case, because the `variable` will be assigned a different value in each iteration.

And by not using `const`, this means that I could change its value inside the loop:

```javascript
let variable = 1;
for (variable of collection) {
    variable = 1000;
    console.log(variable);
}
```

If I use `const` and declare it inside the loop, though, I can't change its value:

```javascript
for (const variable of collection) {
    variable = 1000; // error!
    console.log(variable);
}
```

This gives me an error because [I can't assign another value to a `const` variable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const). That's useful if you want to make sure that the `variable` isn't changed inside the loop.

Another difference is that in the second code, the `variable` still exists after the loop:

```javascript
let variable;
for (variable of collection) {
    console.log(variable);
}
console.log('after', variable); // variable has the value of the last collection's element
```

That's because it was declared outside the loop.

But if I do this:

```javascript
for (const variable of collection) {
    console.log(variable);
}
console.log('after', variable); // error (variable is out of scope and doesn't exist outside the loop)
```

Now the `variable`'s scope is the `for..of` loop, thus it can't be accessed outside the loop. That's useful to limit the variable's scope.

---

Of course you could also use a "traditional" `for`:

```javascript
for (let i = 0; i < collection.length; i++) {
    const variable = collection[i];
    console.log(variable);
}
```

But the `for..of` loop is actually more than just an alternative syntax, because it allows you to loop through any iterable object.

Not all iterable objects have the `length` property, and some might not support the `[]` syntax to access a specific element. For those objects, the `for..of` loop provides a standard way to loop through them, all they have to do is implement the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol).

Just to provide some examples:

```javascript
// A Set doesn't have a way to access individual elements by index
var set = new Set([1, 2, 3, 1, 4, 5]);
for (const n of set) {
    console.log(n);
}

// I can iterate through the keys and respective values of a Map
var map = new Map([ ['name', 'Douglas'], ['age', 42], ['country', 'UK']]);
// and I can also use destructuring assignment: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
for (const [key, value] of map.entries()) {
    console.log(`${key} = ${value}`);
}
```

---

And there are cases where the results are different, such as when looping through the characters of a string:

```javascript
const string = 'abc' + String.fromCodePoint(0x1F60A);
for (const character of string) {
    console.log(character);
}
```

The output is (note the emoji in the end):

```none
a
b
c
😊
```

But with a traditional `for`:

```javascript
for (let i = 0; i < string.length; i++) {
    console.log(string[i]);
}
```

This will print:

```none
a
b
c
�
�
```

That's because `for..of` loops through the Unicode code points, while the traditional loop breaks some of them in surrogate pairs. I know that's *way* beside the point, it was just to show that a `for..of` loop has its own characteristics, and sometimes there's no obvious equivalent using other types of loops (but if you're curious about all this Unicode stuff, take a look at [this answer](https://software.codidact.com/posts/283000/283058#answer-283058)).

---

# Summary

- the `for..of` loop syntax is the way it is, because whoever designed it, decided it that way
- some cases might be interchangeable with a traditional `for` loop, some other cases might not