Skip to content

Instantly share code, notes, and snippets.

@lukehorvat
Last active January 8, 2024 10:32
Show Gist options
  • Save lukehorvat/133e2293ba6ae96a35ba to your computer and use it in GitHub Desktop.
Save lukehorvat/133e2293ba6ae96a35ba to your computer and use it in GitHub Desktop.
Convert ES6 Map to Object Literal
let map = new Map();
map.set("a", 1);
map.set("b", 2);
map.set("c", 3);
let obj = Array.from(map).reduce((obj, [key, value]) => (
Object.assign(obj, { [key]: value }) // Be careful! Maps can have non-String keys; object literals can't.
), {});
console.log(obj); // => { a: 1, b: 2, c: 3 }
@seromenho
Copy link

With for...of

const obj = {};
for (let [key, value] of map) {
  obj[key] = value;
}

@wall-street-dev
Copy link

No spread & no Array.from

const newObject = theMap.keys.reduce((obj, key) => {
                  obj[key] = theMap.get(key);
                  return obj;
                }, {});

@varoot
Copy link

varoot commented Jan 31, 2020

You can also use forEach method

const obj = {};
map.forEach((value, key) => (obj[key] = value));

@broofa
Copy link

broofa commented Feb 22, 2020

@varoot provided the secret sauce.

const obj = Object.fromEntries(map.entries());

@varoot
Copy link

varoot commented Feb 23, 2020

But note that Object.fromEntries is ES2019 so it's not technically "ES6" and might need additional polyfill for Node or browsers.

@varoot provided the secret sauce.

const obj = Object.fromEntries(map.entries());

@lsironic
Copy link

lsironic commented Mar 4, 2020

@varoot

const obj = {};
map.forEach((value, key) => (obj[key] = value));

no need to return anything in forEach.
map.forEach((value, key) => {obj[key] = value});

@leebenson
Copy link

In Node 12+, just Object.fromEntries(map).

@snowyu
Copy link

snowyu commented Jul 21, 2020

Need to think about recurisive map:

const m = new Map()
m.set('submap', new Map())

@snowyu
Copy link

snowyu commented Jul 21, 2020

export function fromMap(map) {
  return Array.from
    ( map.entries()
    , ([ k, v ]) =>
        v instanceof Map
          ? { _mK: k, _mVal: fromMap (v) }
          : { _mK: k, _mVal: v }
    )
}

export function toMap(arr) {
  let m = new Map()
  arr.forEach(item => {
    let v = item._mVal;
    if (Array.isArray(v) && v[0] && v[0]._mK !== undefined) v = toMap(v)
    m.set(item._mK, v)
  })
  return m
}

@marcusflat
Copy link

function fromMap(map) {
  let obj = {}
  for(let[k,v] of map) {
      v instanceof Map 
        ? obj[k] = fromMap(v)
        : obj[k] = v
  }
  return obj
}

@snowyu
Copy link

snowyu commented Aug 9, 2020

@marcusflat: It can not reverse the object to map if so.

@marcusflat
Copy link

@marcusflat: It can not reverse the object to map if so.

function toMap(obj) {
  let map = new Map()
  for(let k of Object.keys(obj)) {
      obj[k] instanceof Object 
        ? map.set(k, toMap(obj[k]))
        : map.set(k, obj[k]);
  }
  return map
}

@snowyu
Copy link

snowyu commented Aug 12, 2020

@marculsflat: your scene is that all object are the Map. but not all objects are the map in some scene.

treeMap =  {
'filepath': {
  name: 'filebasename',
  path: 'filepath',
  stat: new Stat(), // not map
  children: new Map(...)
}

@xgqfrms
Copy link

xgqfrms commented Oct 1, 2020

ES6 ways

  1. Object.fromEntries
const log = console.log;

const map = new Map();
// undefined
map.set(`a`, 1);
// Map(1) {"a" => 1}
map.set(`b`, 2);
// Map(1) {"a" => 1, "b" => 2}
map.set(`c`, 3);
// Map(2) {"a" => 1, "b" => 2, "c" => 3}

// Object.fromEntries ✅
const obj = Object.fromEntries(map);

log(`\nobj`, obj);
// obj { a: 1, b: 2, c: 3 }
  1. ...spread & destructing assignment
const autoConvertMapToObject = (map) => {
  const obj = {};
  for (const item of [...map]) {
    const [
      key,
      value
    ] = item;
    obj[key] = value;
  }
  return obj;
}

const log = console.log;

const map = new Map();
// undefined
map.set(`a`, 1);
// Map(1) {"a" => 1}
map.set(`b`, 2);
// Map(1) {"a" => 1, "b" => 2}
map.set(`c`, 3);
// Map(2) {"a" => 1, "b" => 2, "c" => 3}

const obj = autoConvertMapToObject(map);
log(`\nobj`, obj);
// obj { a: 1, b: 2, c: 3 }

@BinodNagarkoti
Copy link

Major performance hit when you create a new object (with Object.assign) inside every iteration.

Because you're creating a new object literal when you call Array.reduce(fn, {}), you can safely mutate that accumulator object from within the reducer function.

This is WAYYYYY faster:

let obj = Array.from(map).reduce((obj, [key, value]) => {
  obj[key] = value;
  return obj;
}, {});

Unfortunately, you'll never know because gist doesn't send comment notifications... I hope someone finds this comment and it helps them. Email me if it does, so I can be notified this helped someone 😉

this one helped me.

@vjpr
Copy link

vjpr commented Sep 9, 2021

If a value in the map can be an array of maps you need:

const toObject = (map = new Map) => {
  if (!(map instanceof Map)) return map
  return Object.fromEntries(Array.from(map.entries(), ([k, v]) => {
    if (v instanceof Array) {
      return [k, v.map(toObject)]
    } else if (v instanceof Map) {
      return [k, toObject(v)]
    } else {
      return [k, v]
    }
  }))
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment