如何将普通对象转换为ES6映射?

时间:2016-04-15 10:18:24

标签: javascript ecmascript-6

出于某种原因,我无法在MDN docs中找到这个简单的事情(也许我只是错过了它)。

我希望这可行:

const map = new Map({foo: 'bar'});

map.get('foo'); // 'bar'

...但第一行抛出TypeError: (var)[Symbol.iterator] is not a function

如何从普通对象制作地图?我是否真的必须先将其转换为键值对数组?

8 个答案:

答案 0 :(得分:120)

是的,Map构造函数采用一组键值对。

Object.entriesES2017 (19.1.2.5)中提供的新的对象静态方法。

const map = new Map(Object.entries({foo: 'bar'}));

map.get('foo'); // 'bar'

It's currently implemented in Firefox 46+ and Edge 14+ and newer versions of Chrome

如果您需要支持较旧的环境并且不能选择转换,请使用polyfill,例如georg推荐的那个:

Object.entries = typeof Object.entries === 'function' ? Object.entries : obj => Object.keys(obj).map(k => [k, obj[k]]);

答案 1 :(得分:70)

请参阅nils' answer using Object.entries和/或bergi's answer using a generator function虽然在提出问题时Object.entries尚未出现在规范中,it was at Stage 4 ,对于polyfill是安全的,甚至在2016年4月(仅)使用。 (更多关于阶段here。)和生成器功能在ES2015中。 OP特别要求避开中间人,虽然发电机并没有完全避免这种情况,但它比下面的工作做得更好或者(稍微)Object.enties

FWIW,使用Object.entries

  • 创建一个[name, value]数组数组以传递给new Map
  • Map构造函数调用数组上的函数来获取迭代器;数组创建并返回一个数组处理器对象。
  • Map构造函数使用该迭代器对象来获取条目([name, value]数组)并构建地图

使用发电机:

  • 由于调用生成器函数
  • 而创建生成器对象
  • Map构造函数调用该生成器对象上的函数以从中获取迭代器;生成器对象返回本身
  • Map构造函数使用生成器对象(作为迭代器)来获取条目([name, value]数组)并构建映射

所以:少一个中介(来自Object.entries的数组)。

但是,使用Object.entries更简单,并且创建该数组不是99.999%的问题。真的,任何一个。但他们都比下面更好。 : - )

原始答案:

要初始化Map,您可以使用任何将键/值对作为数组返回的迭代器,例如数组数组:

const map = new Map([
    ['foo', 'bar']
]);

从对象到地图没有内置转换,但可以使用Object.keys轻松完成:

const map = new Map();
let obj = {foo: 'bar'};
Object.keys(obj).forEach(key => {
    map.set(key, obj[key]);
});

当然,你可以给自己一个工作者来处理这个问题:

function buildMap(obj) {
    let map = new Map();
    Object.keys(obj).forEach(key => {
        map.set(key, obj[key]);
    });
    return map;
}

然后

const map = buildMap({foo: 'bar'});

或者这里看起来更像l33t(还是那件事吗?)版本:

function buildMap(obj) {
    return Object.keys(obj).reduce((map, key) => map.set(key, obj[key]), new Map());
}

(是的,Map#set会返回地图引用。有人会认为这是reduce abusage 。)

或者我们真的在默默无闻中超越:

const buildMap = o => Object.keys(o).reduce((m, k) => m.set(k, o[k]), new Map());

不,我永远不会那样做。 : - )

答案 2 :(得分:27)

  

我是否真的必须先将其转换为键值对数组?

不,键值对数组的迭代器就足够了。您可以使用以下内容来避免创建中间数组:

function* entries(obj) {
    for (let key in obj)
        yield [key, obj[key]];
}

const map = new Map(entries({foo: 'bar'}));
map.get('foo'); // 'bar'

答案 3 :(得分:8)

The answer by Nils描述如何将对象转换为地图,我觉得这非常有用。但是,OP也想知道这些信息在MDN文档中的位置。虽然在最初提出问题时它可能不存在,但它现在位于标题Object.entries()下的Converting an Object to a Map的MDN页面上,其中指出:

  

将对象转换为地图

     

new Map()构造函数接受entries的迭代。使用Object.entries,您可以轻松地从Object转换为Map

const obj = { foo: 'bar', baz: 42 }; 
const map = new Map(Object.entries(obj));
console.log(map); // Map { foo: "bar", baz: 42 }

答案 4 :(得分:6)

const myMap = new Map(
    Object
        .keys(myObj)
        .map(
            key => [key, myObj[key]]
        )
)

答案 5 :(得分:4)

或者,您可以使用lodash toPairs方法:

const _ = require('lodash');
const map = new Map(_.toPairs({foo: 'bar'}));

答案 6 :(得分:1)

ES6

将对象转换为地图:

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

将地图转换为对象:

const mapToObj = (m) => [...m].reduce( (o,v)=>{ o[v[0]] = v[1]; return o; },{} )

注意:mapToObj函数假定地图键是字符串(否则将失败)

答案 7 :(得分:0)

借助某些JQuery,

const myMap = new Map();
$.each( obj, function( key, value ) {
myMap[key] = value;
});