JavaScript - WeakMap 知多少?

687 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前文我们学习到 Map 类, Map 对象表示一组称为键的值, 每个键关联着一个值, 形成映射关系. 今天来学习另一个(弱映射)类 WeakMap

JavaScript WeakMap

在 JavaScript 中的对象, 我们经常见到的, 对象的键名 key 多为字符串, 但也有时我们需要对象或者数组作为键名的时候,

Object.prototype.toString.call({}) // '[object Object]'
Object.prototype.toString.call(new WeakMap()) // '[object WeakMap]'

可以看到使用 Object.prototype.toString.call()方法对 对象{}new WeakMap()进行判断, 结果 显示两者还是有所不同的

这时候就有两个数据结构 MapWeakMap. 今天主要来学习 WeakMap.

回顾 Map 类(映射)

Map 用于创建一个映射对象, 来存储键名/值映射

let map = new Map() // 这里的 new 创建一个映射对象, 用于键 / 值映射

WeakMap类 (弱映射)

WeakMap 弱映射, 主要用于实现值与对象的关联而不导致内存泄漏. 如下解释:

WeakMap 结构与 Map 结构类似,也是用于生成键值对的集合。但是 WeakMap 只接受对象作为键名( null 除外),不接受其他类型的值作为键名。而且 WeakMap 的键名所指向的对象,不计入垃圾回收机制。

Vue3 源码的时候, 我们会见到这个关键字 WeakMap

// 首先我们要设置两个缓存
let toProxy = new WeakMap() // 根据原始数据查询响应后的数据
let toRaw = new WeakMap() // 根据响应后的数据查询原始数据

然后在进行响应式数据的编写时,对缓存进行查询,已减少不必要的性能消耗

这里的 target 即是要进行响应式的对象, 通过 WeakMap 进行数据缓存

function reactive(target) {
  // 查询缓存
  let observed = toProxy.get(target)
  if (observed) {
    return observed
  }
  if (toRaw.get(target)) {
    return target
  }
  // 响应式
  observed = new Proxy(target, baseHandler)
  // 设置缓存
  toProxy.set(target, observed)
  toRaw.set(observed, target)
  return observed
}