Reputation: 247
I am trying to understand the syntax for iterating through a map in Typescript. The keys in my map are strings. The values are arrays of strings.
Here is some sample code:
let attributeMap: Map<string, string[]> = new Map<string, string[]>();
// sample data
let sampleKey1 = "bob";
// populate map
let value: string[] = attributeMap.get(sampleKey1) || [];
value.push("clever");
attributeMap.set(sampleKey1, value);
value = attributeMap.get(sampleKey1) || [];
value.push("funny");
attributeMap.set(sampleKey1, value);
// try looping through the map
for (let key in attributeMap) {
console.log(attributeMap.get(key));
console.log("WE'RE IN THE MAP!");
}
console.log("done");
When I run this code, the only thing printed is "done".
Why is it that nothing in the map gets printed, nor does the message "WE'RE IN THE MAP"? It's as if the for loop is never entered. Why is that and how would I fix that?
Upvotes: 9
Views: 19101
Reputation: 370699
When you set keys to Maps, the keys do not get put onto the Map instance - they're stored internally in the Map, and can only be accessed by using one of the various Map iteration methods. for..in
only iterates over properties directly on an object or its prototypes.
To iterate over the Map, try something like this instead:
for (const [key, value] of attributeMap.entries()) {
console.log(key, value);
}
for..in
makes sense when your collection is a normal object with key-value pairs on the object itself, but not for Maps, which stores data differently.
When a property is directly on an object, the syntax will usually look something like this:
someObj.someProp = 'someVal';
This puts the someProp
property onto the someObj
object.
But Maps store their data inside the [[MapData]] internal slot of the Map, and not directly on different properties of the Map.
Just as a theoretical exercise, in JS, you could put a property directly on a Map instance and it'll be iterated over with for..in
(basically, abusing a map as an object with own-properties):
const map = new Map();
map.foo = 'bar';
for (const prop in map) {
// ...
}
But that's quite an antipattern and should never be done. Either use an object and set/retrieve properties with dot and bracket notation (and other object methods like Object.entries
), or use a Map and set/retrieve properties with Map.get
and Map.set
and the other Map methods.
Upvotes: 10