1

In the Node.js REPL:

> var map = new Map();
undefined
> map['foo'] = 'bar';
'bar'
> map['bar'] = 'baz';
'baz'
> map
Map { foo: 'bar', bar: 'baz' }
> map.forEach(console.log);
undefined

As you can see, the foo and bar keys are clearly defined within map, but when I try to iterate over them with Map.prototype.forEach, nothing happens - but according to MDN, it should. Note also that Map.prototype.forEach is defined, so it's not just that this method hasn't been implemented yet. I've also tried using a for ... of ... loop, with the same result - the code I provide to be run for each iteration doesn't actually run, even though it should.

I'm on Node.js v4.4.4. I searched the web for "javascript map isn't iterable node" and the like, with no luck.

What's going on here?

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
strugee
  • 2,573
  • 4
  • 16
  • 28
  • `Map` objects don't have properties, they have entries. Create it using `new Map([['foo', 'bar'], ['bar', 'baz']])` – Bergi Sep 22 '16 at 06:13

4 Answers4

5

Not 100% positive, but I think you need to use map.set with Maps.

var map = new Map();
map.set('foo', 'bar');
map.set('bar', 'baz');
map.forEach(console.log);

This will log out each of the items that you are looking for. Because the Map.prototype.forEach is looking for iterable properties, you need to use the set() function to set those iterable properties.

frosty
  • 16,905
  • 5
  • 43
  • 70
  • what in the world? this worked (will accept your answer as soon as I'm allowed), but I can't _imagine_ why it's this way - or, for that matter, why the `map[key]` syntax appeared to "work", but not really, in such a confusing way. anyway, thanks! – strugee Sep 22 '16 at 06:10
  • 2
    oh I see. it's because I was setting a property on the Map, whereas `map.set` is setting the key _inside_ the Map... if that makes sense. – strugee Sep 22 '16 at 06:12
  • 5
    Because a map is an `Object`, you can duck-punch any property that you want onto it. Just like you can say `[].foo = "bar"`, to duck-punch properties onto an array, you can do the same with a Map, or a Function. Thus, it didn't error when you tried to do it. However, Maps use the `Iterator` functionality from ES6, which means that in order for you to get the iterable stuff to work, you need to set values using `.set()` instead of using dotNotation or bracketNotation to set the value. This is how maps work. – frosty Sep 22 '16 at 06:13
1

Map is an abstract data type. Applying the Map constructor with new creates a normal object of course. But the Map itself is abstracted behind its API (Map.prototype.get/set/has/clear etc.):

const map = new Map([["key1", 1], ["key2", 2]]);

// you can mutate the Map object:
map["foo"] = "bar";
map.bar = "baz";

console.log( map );

// but you need to use the Map API to mutate the Map itself:
map.set("key3", 3);

map.forEach(console.log.bind(console));

Note that this is actually the benefit of the new Map type: It separates the data from the program level.

Community
  • 1
  • 1
0

We can use for(){...} operator to iterate ES6 Map

let map0 = new Map([
  ["a", 1],
  ["b", 2],
  ["c", 3]
]);

let map1 = new Map();
for (let [key, value] of myMap) {
    map1.set('_' + k, v * 2);    
}

resulted in

{'_a' => 2, '_b' => 4, '_c' => 6}
Roman
  • 11,040
  • 8
  • 59
  • 67
0

If we want to use .map() iterator, we can use a simple trick for Maps, because there is no such operation for Maps as map(). The approach from Dr. Axel Rauschmayer is: * Convert the map into an array of [key,value] pairs. * Map or filter the array. * Convert the result back to a map.

Example:

let map0 = new Map([
  ["a", 1],
  ["b", 2],
  ["c", 3]
]);

const map1 = new Map(
  [...map0]
  .map(([k, v]) => ['_' + k, v * 2 ])
);

resulted in

{'_a' => 2, '_b' => 4, '_c' => 6}
Roman
  • 11,040
  • 8
  • 59
  • 67