Skip to content

Map

Map

  • Map 是 ES6 引入的一种新的数据结构,类似于对象,但键可以是任意类型。
  • 常用于存储键值对,且有更好的性能和语义。
  • 键值对存储,键可以是任意类型(对象、基本类型等)
  • 按插入顺序迭代
  • 有 size 属性,能直接获取元素数量

迭代

js
const map = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3],
])

for (const [key, value] of map) {
  console.log(`key: ${key}, value: ${value}`)
}
js
const map = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3],
])

map.forEach((value, key) => {
  console.log(`key: ${key}, value: ${value}`)
})

size

js
const map = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3],
])

console.log(map.size) // 3

常见方法

  • set(key, value):添加或更新键值对
  • get(key):获取键对应的值
  • has(key):检查键是否存在
  • delete(key):删除键值对
  • clear():清空所有键值对
  • keys():返回键的迭代器
  • values():返回值的迭代器
  • entries():返回键值对的迭代器

Map 转 Array

可以通过扩展运算符或 Array.from 方法将 Map 转为数组:

js
const map = new Map([
  ['a', 1],
  ['b', 2],
])
const arr1 = [...map] // [['a', 1], ['b', 2]]
const arr2 = Array.from(map) // [['a', 1], ['b', 2]]

只获取键或值:

js
const keys = [...map.keys()] // ['a', 'b']
const values = [...map.values()] // [1, 2]

Map 转 Object

Map 转为普通对象时,需注意键必须为字符串或可以被转换为字符串:

js
const map = new Map([
  ['a', 1],
  ['b', 2],
])
const obj = Object.fromEntries(map) // { a: 1, b: 2 }

如果 Map 的键不是字符串,转换后会变成字符串:

js
const map = new Map([
  [1, 'one'],
  [true, 'yes'],
])
const obj = Object.fromEntries(map) // { '1': 'one', 'true': 'yes' }

WeakMap

  • WeakMap 是 ES6 引入的一种新的键值对集合,键必须是对象且为弱引用。
  • 常用于存储与对象相关的数据,且不影响垃圾回收。
  • WeakMap 的键只能是对象,不能是基本类型。
  • 没有 size 属性,不能遍历。
  • 常用方法:set、get、has、delete。

使用示例

js
const wm = new WeakMap()
const obj = {}
wm.set(obj, 'data')
console.log(wm.get(obj)) // 'data'
wm.has(obj) // true
wm.delete(obj)

提示

Vue3 源码中大量使用 WeakMap 来存储与组件实例相关的数据,以避免内存泄漏。

常见的:

  • Vue3 响应式系统中使用 WeakMap 来存储对象与其代理对象之间的映射关系。

常见面试题

Object、Map、WeakMap 的区别?

  1. 键的类型:
    • Object:键必须是字符串或符号(Symbol)。
    • Map:键可以是任意类型(包括:对象、函数、NaN 等)。Map 用类似 === 比较,但 NaN 相等。
    • WeakMap:键必须是对象,不能是原始类型。并且以弱引用保存。
  2. 可枚举性 / 迭代:
    • Object:可以用 for...inObject.keys/values/entriesfor...of 结合 Object.entries 进行迭代。
    • Map: 可以直接用 for...ofMap.prototype.forEach 进行迭代。
    • WeakMap:不能被枚举或迭代。
  3. size:
    • Object:没有内置的 size 属性,但可使用 Object.keys(obj).length 获取键值对数量。
    • Map:有内置的 size 属性,可以直接获取键值对的数量。
    • WeakMap:没有 size 属性,无法获取键值对的数量。
  4. 垃圾回收:
    • ObjectMap:只要有引用存在,键值对就不会被垃圾回收。
    • WeakMap:键是弱引用,如果没有其他引用指向该对象,垃圾回收器可以回收该对象,从而释放内存。

提示

弱引用:如果没有其他引用指向该对象,垃圾回收器可以回收该对象,从而释放内存。

基于 MIT 许可发布