出于某种原因,我无法在MDN docs中找到这个简单的事情(也许我只是错过了它)。
我希望这可行:
const map = new Map({foo: 'bar'});
map.get('foo'); // 'bar'
...但第一行抛出TypeError: (var)[Symbol.iterator] is not a function
如何从普通对象制作地图?我是否真的必须先将其转换为键值对数组?
答案 0 :(得分:120)
是的,Map
构造函数采用一组键值对。
Object.entries
是ES2017 (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;
});