44

I'm using repl.it/languages/javascript.

Do I have to convert it to an object before I print it out?

I've tried

    const mapObject = new Map();
    
    mapObject.set(1, 'hello');
    
    console.log(JSON.stringify(mapObject));
    console.log(mapObject);

The results are always empty object.

When I use

console.log([...mapObject]);

It prints out an array format.

Zach
  • 539
  • 1
  • 4
  • 22
newguy
  • 5,668
  • 12
  • 55
  • 95

8 Answers8

54

There is a more simpler solution you can try.

const mapObject = new Map();
mapObject.set(1, 'hello');

console.log([...mapObject.entries()]);
// [[1, "hello"]]

console.log([...mapObject.keys()]);
// [1]

console.log([...mapObject.values()]);
// ["hello"]
mplungjan
  • 169,008
  • 28
  • 173
  • 236
samehanwar
  • 3,280
  • 2
  • 23
  • 26
  • Works well with stringify: console.log( JSON.stringify([... mapObject.entries()]) ) – German Khokhlov Jun 30 '23 at 12:09
  • If I try this, I get an error saying "Type 'IterableIterator' is not an array type". OK, in my case the Map ist more complicated than that defined in the snippet. But if the solution only works for those simple Maps it's not worth considering. – MDickten Jul 19 '23 at 07:54
9

Note: This answer is only relevant to the repl.it sandbox environment OP is using

Since you said in the comments that you're using repl.it, there's a trick you can use to write your own "logging strategy".

Note that you shouldn't use this trick in production, mainly because it edits a native prototype. In some Node environment, in your own code, it could be useful though.

The idea is to create an inspect method for Map that iterates over the entries:

Map.prototype.inspect = function() {
  return `Map(${mapEntriesToString(this.entries())})`
}

function mapEntriesToString(entries) {
  return Array
    .from(entries, ([k, v]) => `\n  ${k}: ${v}`)
    .join("") + "\n";
}

You can see that repl.it supports it here

console.log(new Map([["a", 1], ["b", 2]]));
// Logs:
/*
Map(
  a: 1
  b: 2
)
*/
user3297291
  • 22,592
  • 4
  • 29
  • 45
  • 2
    Nice one. I just finished something similar, but I chose to bastardise their `console.log` instead :) https://repl.it/KBdU – Dave Salomon Aug 08 '17 at 14:53
  • 1
    @DaveSalomon Nice! Feels like "We're in an online sandbox environment; let's break *all* the native prototypes and default implementations!" ;) Still, both approaches can help in the debugging process, so it's nice to see what can be done. – user3297291 Aug 08 '17 at 14:56
6

For simple maps that are of depth 1, just use Object.fromEntries([...map]) to convert your object entries array back to a console loggable object:

const simpleObj = {
  a: [1, 2, 3],
  b: {c: {d: 42}}
};
const map = new Map(Object.entries(simpleObj));
console.log(Object.fromEntries([...map]));

This fails for complex nested maps, however. For that, we can recursively convert any Maps to objects and then log it as normal. Here's a proof-of-concept on a complex structure combining plain objects, Maps, arrays and primitives. Don't expect it to cover every edge case out of the box, but feel free to point out improvements.

const convertMapToObjDeeply = o => {
  const recurseOnEntries = a => Object.fromEntries(
    a.map(([k, v]) => [k, convertMapToObjDeeply(v)])
  );
  
  if (o instanceof Map) {
    return recurseOnEntries([...o]);
  }
  else if (Array.isArray(o)) {
    return o.map(convertMapToObjDeeply);
  }
  else if (typeof o === "object" && o !== null) {
    return recurseOnEntries(Object.entries(o));
  }
  
  return o;
};

const mkMap = o => new Map(Object.entries(o));

const map = mkMap({
  a: 42, 
  b: [1, 2, 3, mkMap({d: mkMap({ff: 55})})],
  c: mkMap({
    e: [4, 5, 6, {f: 5, x: y => y}, mkMap({g: z => 1})]
  }),
  h: {i: mkMap({j: 46, jj: new Map([[[1, 6], 2]])})},
  k: mkMap({l: mkMap({m: [2, 5, x => x, 99]})})
});

console.log(convertMapToObjDeeply(map));
ggorlen
  • 44,755
  • 7
  • 76
  • 106
6

I realize this is most likely intended for the browser console but this also occurs in Node. So, you may use this in Node to view Maps (or an Object that may contain Maps):

import * as util from "util";

const map: Map<string, string> = new Map();
map.set("test", "test");

const inspected: string = util.inspect(map);

console.log(inspected);
Schmeedty
  • 83
  • 1
  • 5
2

you can use console.log(mapObject.values())

omer
  • 2,435
  • 2
  • 24
  • 28
2

Try this:

let mapObject = new Map();
mapObject.set("one", "file1");
mapObject.set("two", "file2");
mapObject.set("three", "file3");
console.log([...mapObject.entries()]);

the output will be:

[ [ 'one', 'file1' ], [ 'two', 'file2' ], [ 'three', 'file3' ] ]

The problem with this solution, is that the output changes if we add a previous string:

console.log("This is a map: " + [...mapObject.entries()]);

the output will be:

This is a map: one,file1,two,file2,three,file3

the solution can be found here

David Leal
  • 6,373
  • 4
  • 29
  • 56
1

Simplest and most human readable option: console.table

const mapObject = new Map();
mapObject.set(1, 'hello');
mapObject.set(2, 'world');
mapObject.set('foo', 'bar');

console.table(mapObject);

NodeJS output looks like this:

┌───────────────────┬───────┬─────────┐
│ (iteration index) │  Key  │ Values  │
├───────────────────┼───────┼─────────┤
│         0         │   1   │ 'hello' │
│         1         │   2   │ 'world' │
│         2         │ 'foo' │  'bar'  │
└───────────────────┴───────┴─────────┘

Chrome dev tools console output looks like this:

enter image description here

Jacob Stamm
  • 1,660
  • 1
  • 29
  • 53
0

In my case (regular browser console in Chrome V 115, Immutable Map) I could use

console.dir(myMapObject.toJS());

It contained a great deal of information more than I needed, but better too much than too little.

MDickten
  • 105
  • 1
  • 10