Reputation: 53799
I was reading this example of using a for.. of
loop on a Map, and I was a bit confused with this syntax:
var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
console.log(key + " = " + value);
}
Specifically, I don't understand the array destructuring that is happening. I understand that you can use array destructuring to do something like let [one, two] = [1, 2];
, but what is happening in this example? myMap
isn't an array so why is this getting the correct values?
Another question I have is why is the order key, value
in the destructuring, but when you do a forEach()
the order is value, key
, like here:
myMap.forEach((value, key) => {
console.log(key + " = " + value);
});
Upvotes: 37
Views: 43252
Reputation: 2867
All, Allow me to add that how the asked syntax works.
The Map.entries() method returns a new Iterator object that contains the [key, value] pairs for each element in the Map object in insertion order.
for (var [key, value] of myMap.entries()) {
console.log(key + " = " + value);
}
But in your question you haven't added .entries but still it works. The reason is the symbol.Iterator points by default to Map.prototype.entries() function. This is the reason you include or exclude it works both ways. As explained above the .entries() function returns an Iterator of array([key,value] pair).
Upvotes: -3
Reputation: 99980
Slightly off topic but as an aside:
myMap.forEach((v,k) => {});
is about 50% more performant than
for (var [key, value] of myMap) {
}
so perhaps consider using Map.prototype.forEach
(not to be confused with Array.prototype.forEach
).
Upvotes: 8
Reputation: 43042
myMap isn't an array so why is this getting the correct values?
Map's prototype has a [Symbol.iterator] property, which means instances of Map implement the iterator contract.
for of loops make use of iterators to loop over objects.
In other words, for of loops don't need arrays, they need iteratables. Arrays are just one type of iterable, maps are another.
In the case of maps the iterator yields a 2-element array consisting of key and value for each iteration. It also has additional methods that allow you to iterate over just the keys or the values.
Upvotes: 2
Reputation: 224867
for (var [key, value] of myMap) {
console.log(key + " = " + value);
}
is like
for (let pair of myMap) {
var [key, value] = pair;
console.log(key + " = " + value);
}
So it’s not myMap
that has to be an array for the destructuring to work; rather, each of its elements has to be an array when it’s iterated over, and iterating over a map indeed produces arrays (key/value pairs).
Map#forEach
’s argument order is probably for consistency with Array#forEach
, which calls the function with arguments (item, index)
; it, in turn, probably does that because you don’t always need the index.
Upvotes: 56