Map/WeakMap

Map

Map是一组键值对的结构,用于解决以往不能用对象做为键的问题

  • 具有极快的查找速度
  • 函数、对象、基本类型都可以作为键或值

声明定义

可以接受一个数组作为参数,该数组的成员是一个表示键值对的数组。

const m = new Map([
    ['mkimq', '在线文档'],
    ['mkimq.com', '网站']
])

console.log(m.get('mkimq'))

使用set 方法添加元素,支持链式操作

const map = new Map()

map.set('mkimq', '在线文档').set('age', 18)
console.log(map.entries())

对于键是对象的Map, 键保存的是内存地址,值相同但内存地址不同的视为两个键。

获取数量

获取数据数量

console.log(map.size)

元素检测

检测元素是否存在

console.log(map.has('mkimq'))

读取元素

map.get('mkimq')

删除元素

使用 delete() 方法删除单个元素

map.delete('mkimq')

使用clear方法清除Map所有元素

map.clear()

遍历数据

使用 keys()/values()/entries() 都可以返回可遍历的迭代对象。

const map = new Map([['mkimq', '在线文档'], ['age', 18]])

console.log(map.keys())
console.log(map.values())
console.log(map.entries())

可以使用keys/values 函数遍历键与值

for (const key of map.keys()){
    console.log(key)
}

for (const value of map.values()){
    console.log(value)
}

使用for/of遍历操作,直播遍历Map 等同于使用entries() 函数

for (const [key, value] of map) {
    console.log(`${key}=>${value}`)
}

使用forEach遍历操作

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

数组转换

可以使用展开语法 或 Array.form 静态方法将Set类型转为数组,这样就可以使用数组处理函数了

console.log(...map)
console.log(...map.entries())
console.log(...map.values())
console.log(...map.keys())

节点集合

map的key可以为任意类型,下面使用DOM节点做为键来记录数据。

<body>
    <div desc="在线文档">mkimq</div>
    <div desc="站点">mkimq.com</div>
</body>

<script>
    const divMap = new Map()
    const divs = document.querySelectorAll('div')

    divs.forEach(div => {
        divMap.set(div, {
            content: div.getAttribute('desc')
        })
    });
    divMap.forEach((config, elem) => {
        elem.addEventListener('click', function() {
            alert(divMap.get(this).content)
        })
    })
</script>

WeakMap

WeakMap 对象是一组键/值对的集

  • 键名必须是对象
  • WeaMap对键名是弱引用的,键值是正常引用
  • 垃圾回收不考虑WeaMap的键名,不会改变引用计数器,键在其他地方不被引用时即删除
  • 因为WeakMap 是弱引用,由于其他地方操作成员可能会不存在,所以不可以进行forEach()遍历等操作
  • 也是因为弱引用,WeaMap 结构没有keys(),values(),entries()等方法和 size 属性
  • 当键的外部引用删除时,希望自动删除数据时使用 WeakMap

声明定义

以下操作由于键不是对象类型将产生错误

错误示范

new WeakMap('mkimq')

将DOM节点保存到WeakMap

const map = new WeakMap()

document
    .querySelectorAll('div')
    .forEach(item => map.set(item, item.innerHTML))

基本操作

下面是WeakMap的常用指令

const mk = new WeakMap()

const arr = ['mkimq']

// 添加
mk.set(arr, 'mkimq')

// 删除
mk.delete(arr)

// 检索判断
mk.has(arr)

垃圾回收

WakeMap的键名对象不会增加引用计数器,如果一个对象不被引用了会自动删除。

  • 下例当hd删除时内存即清除,因为WeakMap是弱引用不会产生引用计数
  • 当垃圾回收时因为对象被删除,这时WakeMap也就没有记录了
const mk = new WeakMap()
let arr = {}

mk.set(arr, 'mkimq')
console.log(mk.has(arr))

arr = null
console.log(mk)
贡献者: mankueng