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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36644438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:21:38  来源:igfitidea点击:

How to convert a plain object into an ES6 Map?

javascriptecmascript-6

提问by callum

For some reason I can't find this simple thing in the MDN docs(maybe I'm just missing it).

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

I expected this to work:

我希望这能奏效:

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

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

...but the first line throws TypeError: (var)[Symbol.iterator] is not a function

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

How do I make a Map from a plain object? Do I really have to first convert it into an array of arrays of key-value pairs?

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

回答by nils

Yes, the Mapconstructor takes an array of key-value pairs.

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

Object.entriesis a new Object static method available in ES2017 (19.1.2.5).

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

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

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

If you need to support older environments and transpilation is not an option for you, use a polyfill, such as the one recommended by georg:

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

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

回答by T.J. Crowder

Please see nils' answer using Object.entriesand/or bergi's answer using a generator function.Although Object.entrieswasn't in the spec yet when the question was asked, it was at Stage 4, so safe to polyfill and use on even back in April 2016 (just). (More on the stages here.) And generator functions were in ES2015. The OP specifically asked to avoid intermediaries, and while the generator doesn't completely avoid that, it does a better job than the below or (slightly) Object.enties.

使用生成器函数查看nils 的答案Object.entries和/或bergi 的答案尽管Object.entries在提出问题时还没有在规范中,但它处于 Stage 4,因此即使在 2016 年 4 月(仅)就可以安全地进行 polyfill 和使用。(更多关于这里的阶段。)生成器函数在 ES2015 中。OP 特别要求避免中间人,虽然生成器并没有完全避免这种情况,但它比下面或(稍微)做得更好Object.enties

FWIW, using Object.entries:

FWIW,使用Object.entries

  • Creates an array of [name, value]arrays to pass to new Map
  • The Mapconstructor calls a function on the array to get an iterator; the array creates and returns an array interator object.
  • The Mapconstructor uses that iterator object to get the entries (the [name, value]arrays) and build the map
  • 创建[name, value]要传递给的数组数组new Map
  • Map构造函数调用数组以得到一个迭代器上的功能; 该数组创建并返回一个数组迭代器对象。
  • Map构造函数使用了迭代器对象获取的条目(该[name, value]阵列),并建立映射

Using the generator:

使用生成器:

  • Creates a generator object as a result of calling the generator function
  • The Mapconstructor calls a function on that generator object to get an iterator from it; the generator object returns itself
  • The Mapconstructor uses the generator object (as an iterator) to get the entries (the [name, value]arrays) and build the map
  • 作为调用生成器函数的结果创建生成器对象
  • Map构造函数调用生成器对象的函数从它那里得到一个迭代器; 生成器对象返回自身
  • Map构造函数使用生成器对象(作为一个迭代)来获得条目(在[name, value]阵列)和构建地图

So: One fewer intermediary (the array from Object.entries).

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

However, using Object.entriesis simpler and creating that array isn't an issue 99.999% of the time. So really, either one. But they're both better than the below. :-)

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



Original answer:

原答案:

To initialize a Map, you can use any iterator that returns key/value pairs as arrays, such as an array of arrays:

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

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

There's no built-in conversion from object to map, but it's easily done with Object.keys:

没有从对象到地图的内置转换,但它很容易完成Object.keys

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

You can, of course, give yourself a worker function to handle that:

当然,你可以给自己一个工作函数来处理:

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

Then

然后

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

Or here's a more l33t-looking (is that still a thing?) version:

或者这里有一个看起来更像 l33t 的(这仍然是一个东西吗?)版本:

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

(Yes, Map#setreturns the map reference. Some would argue this is an abusageof reduce.)

(是的,Map#set返回地图参考。有些人认为,这是一abusagereduce。)

Or we can reallygo over-the-top on obscurity:

或者我们真的可以在默默无闻的事情上过头了:

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

No, I would never do that for real. :-)

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

回答by Bergi

Do I really have to first convert it into an array of arrays of key-value pairs?

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

No, an iterator of key-value pair arrays is enough. You can use the following to avoid creating the intermediate array:

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

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

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

回答by Andrew Willems

The answer by Nilsdescribes howto convert objects to maps, which I found very useful. However, the OP was also wondering where this information is in the MDN docs. While it may not have been there when the question was originally asked, it is now on the MDN page for Object.entries()under the heading Converting an Object to a Mapwhich states:

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

Converting an Object to a Map

The new Map()constructor accepts an iterable of entries. With Object.entries, you can easily convert from Objectto Map:

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

将对象转换为地图

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 }

回答by Ohar

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

回答by Maurits Rijk

Alternatively you can use the lodash toPairsmethod:

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

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

回答by Yair Levy

ES6

ES6

convert object to map:

将对象转换为地图:

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

convert map to object:

将地图转换为对象:

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

Note: the mapToObj function assumes map keys are strings (will fail otherwise)

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

回答by Patrick Mutuku

With the help of some JQuery,

在一些 JQuery 的帮助下,

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