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

IT技术 javascript ecmascript-6
2021-01-19 05:23:07

出于某种原因,我在MDN 文档中找不到这个简单的东西(也许我只是想念它)。

我希望这能奏效:

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

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

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

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

6个回答

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

Object.entriesES2017 (19.1.2.5) 中一个新的 Object 静态方法

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

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

它目前在 Firefox 46+ 和 Edge 14+ 以及更新版本的 Chrome 中实现

如果您需要支持较旧的环境并且转译不适合您,请使用 polyfill,例如由 georg 推荐的:

Object.entries = typeof Object.entries === 'function' ? Object.entries : obj => Object.keys(obj).map(k => [k, obj[k]]);
不仅是 Node7 中的 Object.entries,它也是 ES2017 最终规范的一部分。因此,这应该是公认的答案,IMO
2021-03-16 05:23:07
@AnilRedshift - 好吧,这个或生成器函数回答,因为 OP 要求避免中介的解决方案。
2021-03-18 05:23:07
“polyfill”将是相当微不足道的: Object.entries = obj => Object.keys(obj).map(k => [k, obj[k]])
2021-03-19 05:23:07
Object.entries 登陆 Node 7.x 正确(没有标志)顺便说一句
2021-03-30 05:23:07
不幸的是,它不会。
2021-04-01 05:23:07

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

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

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

const map = new Map(entries({foo: 'bar'}));
map.get('foo'); // 'bar'
很好的例子 - 只是给其他人的一个注释,您可能希望if(!obj.hasOwnProperties(key)) continue;在 for 循环条件之后立即执行,以确保您不会产生从对象原型继承的属性(除非您信任该对象,但在使用in作为一个好习惯)。
2021-03-15 05:23:07
是的,我认为不打扰是最好的做法。您应该相信所有值得枚举的对象(即键值映射)不具有任何可枚举的继承属性。(是的,当然避免枚举数组)。如果您遇到枚举其他内容的罕见情况,并且您很烦恼,您至少应该使用call. 那里推荐的所有约定obj.hasOwnProperties(key)似乎都不知道他们在做什么。
2021-03-17 05:23:07
@Puiu 不,你不应该,这是一个坏习惯。如果你不信任这个对象,你也不能信任它的.hasOwnProperty属性,你必须使用Object.prototype.hasOwnProperty.call(obj, key)
2021-03-28 05:23:07
将 anObject转换为 aMap是一项昂贵的操作,并且 OP 特别要求提供一种没有中间体的解决方案。那么为什么这不是例外的答案呢?好吧,问这个可能是徒劳的,它只是让我很烦。
2021-04-06 05:23:07
@tmvnty 您可能需要拼出 type function* entries<T>(obj: T): Generator<readonly [keyof T, T[keyof T]]> {…}yield [key, obj[key]] as const;将帮助 TypeScript 意识到它产生的是元组,而不是数组。
2021-04-08 05:23:07

Nils 的回答描述了如何将对象转换为地图,我发现这非常有用。但是,OP 也想知道此信息在 MDN 文档中的何处。虽然最初提出问题时它可能不存在,但现在它位于Object.entries()的 MDN 页面上,标题为将对象转换为映射,其中指出:

将对象转换为地图

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

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

ES6

将对象转换为地图:

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

将地图转换为对象:

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

注意:mapToObj 函数假定映射键是字符串(否则会失败)

const myMap = new Map(
    Object
        .keys(myObj)
        .map(
            key => [key, myObj[key]]
        )
)
@Ohar's 和 @TJCrowder's 解决方案的融合:var buildMap2 = o => new Map(Object.keys(o).map(k => [k, o[k]]));.
2021-03-23 05:23:07
谢谢,因为我也需要对对象键进行排序!
2021-03-30 05:23:07