1

All the examples I find online for iterating over a Map using for...of are in this format:

for (const [key, val] of map)
    console.log(`${key} maps to ${val}`);

What about using previously declared variables? As in:

let key, val;
for ([key, val] of map)
    console.log(`${key} maps to ${val}`);

This works, but it also works if I never declare key or val, as in:

for ([key, val] of map)
    console.log(`${key} maps to ${val}`);

So in the second example, is the loop using the variables I declared, or is it implicitly declaring new ones within the scope of the loop? I'm not sure how much it matters, but I'd like to understand this all the same. I can't think of a way to test this that proves it one way or another, so I'm posing the question here. I'm probably just confused by the fact that I am enclosing the variables in brackets. In this example I am confident that my previously declared variable is the one being used in the loop, though I have no way to prove it:

let val;
for (val of array)
    console.log(val);

So I would guess that in the second example the loop is using my previously declared variables, but I'm just guessing. This [key, val] of syntax is novel to me and the docs and examples online don't touch on this aspect of it. The way JavaScript allows you to use undeclared variables, but seemingly only if you assign a value to them, is odd, and not a feature I plan to take advantage of any time soon.

Sideways S
  • 601
  • 7
  • 12
  • 1
    "*it also works if I never declare `key` or `val`*" - no it does not. Use strict mode to get an exception from undeclared variables! [This does not "implicitly declare" them in the correct scope, instead it assigns global variables](http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html). You never want that. – Bergi Aug 01 '23 at 09:25

1 Answers1

1

When you declare loop variables outside a loop with let there's no problem of reusing them but that would be considered useless unless you want to handle the last values assigned to them in the loop.

When you don't declare (define) the variables they will be considered as global (a property of the global object (window/globalThis)).

But in the strict mode you will get an error. Using implicit global variables is NO-NO since you can share some variables between different code without knowing thus breaking these code pieces at runtime.

That's why working in the strict mode is mandatory.

To avoid run time errors use Eslint's no-undef rule:
https://eslint.org/docs/latest/rules/no-undef

<script>

  const map = new Map;
  map.set('test-key', 'test-val');

  for ([key, val] of map)
      console.log(`${key} maps to ${val}`);

  console.log('window.key', window.key);
  console.log('window.val', window.val);

</script>

<script>

'use strict';

  const map2 = new Map;
  map2.set('test-key2', 'test-val2');

  for ([key2, val2] of map2)
      console.log(`${key2} maps to ${val2}`);

  console.log('window.key2', window.key2);
  console.log('window.val2', window.val2);

</script>
Alexander Nenashev
  • 8,775
  • 2
  • 6
  • 17
  • 1
    @SidewaysS using the same ’ let i' for loops is unusual in js. also it makes code harder to read and maintain since instead of deleting just a loop you need to delete 'let i' but first check whether it's used in another loop. on the other hand performance won't be improved – Alexander Nenashev Aug 01 '23 at 17:59
  • *"When you declare loop variables outside a loop...that would be considered useless unless you want to handle the last values assigned to them in the loop."* - I do it because I already have an `i` or other reusable variable declared; it avoids redeclaring it repeatedly. In this particular case I reuse `key` to iterate other loops, but I don't reuse `val`, and I'm accustomed to declaring various things at the top of a function I also don't like the idea of redeclaring/defining a variable inside a nested loop, so I avoid that. Is all that considered bad style, even truly pointless? – Sideways S Aug 01 '23 at 18:11
  • by default Eslint highlights unused variables, so that part of it doesn't bother me. But your point is taken. If there is performance penalty, even in nested loops, and this is the currently accepted standard style, then I'll start adopting it. Thanks for all the feedback. – Sideways S Aug 01 '23 at 21:03
  • I did upvote it, but I have never accepted an answer before. I had to look up how to do it. Just did it. Thanks. – Sideways S Aug 01 '23 at 21:09
  • @SidewaysS the accepting gives 15 points and more precious in terms of reputation, thanks! – Alexander Nenashev Aug 01 '23 at 21:13