Appearance
Map
Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者基本类型)都可以作为一个键或一个值。
Map
js
const map = new Map()
const map2 = new Map([
['key1', 'value1'],
['key2', 'value2']
])
const map3 = new Map(map2)
// 操作
map.set(key, value)
map.get(key)
map.has(key)
map.delete(key)
map.clear()
// 大小
map.size
// 生成
map.keys()
map.values()
map.entries()
// 迭代
mpa.forEach(fn)
for (const [key, value] of map) {
}
Map 与 Object
- 额外数据:Map 不包含额外的键,Object 有原型链,可能与现有键冲突;
js
const map = new Map()
const obj = {}
map.get('toString') // undefined
obj.toString // function () {}
- 键类型:Map 键可以是任意类型,Object 必须是一个 String 或者 Symbol;
js
const map = new Map()
const obj = {}
const a = { name: '张三' }
const b = { name: '李四' }
// map 保存两个值
map.set(a, a)
map.set(b, b)
// obj 只保存最后一次的 b 值
obj[a] = a
obj[b] = b
- 大小计算:Map 大小通过 size 查看,Object 需要手动计算;
js
const map = new Map()
const obj = {}
map.set('name', '张三')
obj.name = '李四'
map.size // 1
Object.keys(obj).length // 1
- 迭代方式:Map 可直接通过 for...of,迭代,Object 通过 for...in 迭代,但会受原型链的影响;
js
const map = new Map()
const obj = {}
Object.prototype.extra = '额外数据'
for (const item of map) {
}
for (const item in obj) {
// extra 会被便利
}
- JSON.stringify 序列化:Map 需要自定义 toJSON 函数,Object 可直接被序列化;
js
const map = new Map()
const obj = {}
map.set('name', '张三')
obj.name = '李四'
JSON.stringify(map) // {}
JSON.stringify(obj) // {"name":"李四"}
map.toJSON = function () {
return Object.fromEntries(this)
}
JSON.stringify(map) // {"name":"李四"}
Map 与 WeakMap
- Map 中 key 可以是任意类型,WeakMap 中 key 只能是对象;
- Map 可删除 key,WeakMap 不能删除,也无法查看大小;
- Map 可迭代,WeakMap 不能;
- Map 对 key 持续引用无法回收,WeakMap 对 key 是弱引用,不影响垃圾回收器的工作。
vue
<template>
<el-button @click="onClick">执行</el-button>
<el-button @click="onStop">停止</el-button>
</template>
<script setup>
const map = new Map()
const weakmap = new WeakMap()
let timer
function onClick() {
;(function () {
let foo = { foo: 1 }
let bar = { bar: 2 }
map.set(foo, 1)
weakmap.set(bar, 2)
foo = null
bar = null
})()
onStop()
timer = setInterval(() => {
console.log(weakmap)
console.log(map)
}, 1000)
}
function onStop() {
clearInterval(timer)
}
</script>