Map 与对象之间的相互转换

23,294 阅读2分钟

by @zhangbao(zhangbao) #0108

这里所谓的“对象”是指使用类似 var obj = {}var obj = new Object() 等方式声明的普通对象。

概览

  • 从对象转为 Map :new Map(Object.entries(obj))
  • 从 Map 转为对象:Object.fromEntries(map.entries())

image.png

Map 的两种创建方式

我们创建 Map 时,除了下面这种方式

image.png

还可以使用 new Map(iterable) 语法:

image.png

传入的数组参数,是由一个个键值对([key, value])组成的。这种创建方式,比使用 map.set 更加简洁和方便。

map.entries()

上面的一个个 [key, value] 又称为 entry。我们能行 entries 得到 map,那么也能从 map 得到 entries。需要使用 Map.prototype.entries() 这个 Map 实例上定义的方法。

还是以上面的变量 map 举例:

image.png

map.entries() 得到的结果是是一个迭代对象(MapIterator)。借助 Array.from 可以将迭代对象转为真实数组

那么,问题来了——Map 与对象之间是如何相互转换的呢?答案是借助 entries 这个数据结构

因此,我们先来认识一下 Object.entries 方法。

Object.entries

顾名思义,Object.entries 是用来将一个对象转为 entries 结构形式的。

下面举一个例子:

image.png

这样,我们就能从一个对象得到它的 entries 结构形式了。再带入 new Map()

image.png

现在就完成了“对象 -> Map”的转换了。

💡 提示: 值得注意的是,由于对象属性类型的限制(即对象属性名类型只能是字符串或 Symbol 值)。从对象转成 Map 时,Map key 的类型最多只会有两种:字符串或 Symbol 值。

Object.fromEntries

Object.entries,就有 Object.fromEntries。后者正是前者的反向操作。语法如下:

Object.fromEntries(iterable)

举个例子:

image.png

当然,上面的演示非常无聊。正儿八经得与 map.entries 结合使用才方便呢。

map.entries 结合使用:

map.entries 方法上面已有介绍。此方法用来将 Map 转为迭代对象的表现形式。

let map = new Map([
  ['1',  'str1'],
  [1,    'num1'],
  [true, 'bool1']
]);

Object.fromEntries(map.entries())
// {
//   "1": "num1",
//   "true": "bool1"
// }

从上面的转换为对象的结果中,我们可以看见 ['1', 'str1'] 这个键值对消失了,保留下来的是 [1, 'num1']。而且 1 也变为 "1" 了。原因在于,对象的属性名只能是字符串或 Symbol 值两种,这是与 Map 的 key 不同的地方(Map 的 key 可以是任意类型的)。在从“Map -> 对象”的过程中,所以非 Symbol 类型的 key 最终都会被 Object.fromEntries 方法处理,转为字符串的表现形式。

(完)