在看vue3源码的时候,看到WeakMap
和WeakSet
,不是很明白,平时只用Set
做数组去重。所以趁这个机会好好学一下,查缺补漏。
Set 和 Map 主要的应用场景在于 数据重组 和 数据储存
Set 是一种叫做集合的数据结构,Map 是一种叫做字典的数据结构
Map
Map
区别与Object
的最大的特点是,它能存储任意类型的key
。
举个例子:
let map = new Map()
let john = { name: 'John' }
map.set('1', 'str1') // a string key
map.set(1, 'num1') // a numeric key
map.set(true, 'bool1') // a boolean key
map.set(john, 123) // a object key
console.log(map.get(1)) // 'num1'
console.log(map.get('1')) // 'str1'
console.log(map.get(true)) // 'bool1'
console.log(map.get(john)) // 123
console.log(map.size) // 4
Map
会保留key
的类型,而Object
会把key
转换为string
(Object
的key
还可以是Symbol
)。
属性和操作方法:
size
属性:返回Map
结构的成员总数Map.prototype.set(key, value)
:向Map
中添加或更新元素Map.prototype.get(key)
:读取key
对应的键值,如果找不到key
,返回undefined
Map.prototype.has(key)
:判断Map
对象中是否有Key
所对应的值,有返回true
,否则返回false
Map.prototype.delete(key)
:delete
方法删除某个键,返回true
。如果删除失败,返回false
Map.prototype.clear()
:清除所有成员,没有返回值
遍历方法:
Map.prototype.keys()
:返回键名的遍历器。Map.prototype.values()
:返回键值的遍历器。Map.prototype.entries()
:返回所有成员的遍历器。Map.prototype.forEach()
:遍历 Map 的每个成员。
WeakMap
WeakMap
结构与 Map
结构类似,区别在于:
WeakMap的键名只能是对象,且是弱引用对象。 在没有其他引用和该键引用同一对象,这个对象将会被垃圾回收(相应的key则变成无效的),所以,WeakMap 是不能被遍历的。
Set
Set
区别与数组的最大特点是成员无序且唯一,成员可以是任意类型。
Set 的属性、操作方法及遍历方法与Map类似
WeakSet
WeakSet
与 Set
的区别是,它的成员都是对象且都是被弱引用的,即垃圾回收机制不考虑 WeakSet
对该对象的应用。
应用
上面的学完之后,可以根据需要选择自己需要的数据结构。
下面介绍几种应用场景:
- 数组去重
Array.from(new Set([1, 2, 3, 1, 2])) // [1, 2, 3]
- 实现并集
(Union)
、交集(Intersect)
和差集
let set1 = new Set([1, 2, 3])
let set2 = new Set([4, 3, 2])
let intersect = new Set([...set1].filter(value => set2.has(value))) // Set {2, 3}
let union = new Set([...set1, ...set2]) // Set {1, 2, 3, 4}
let difference = new Set([...set1].filter(value => !set2.has(value))) // Set {1}
- WeakMap, vue3 源码 track函数收集依赖部分
// 是否应该收集依赖
let shouldTrack = true
// 当前激活的 effect
let activeEffect
// 原始数据对象 map
const targetMap = new WeakMap()
function track(target, type, key) {
if (!shouldTrack || activeEffect === undefined) {
return
}
let depsMap = targetMap.get(target)
if (!depsMap) {
// 每个 target 对应一个 depsMap
targetMap.set(target, (depsMap = new Map()))
}
let dep = depsMap.get(key)
if (!dep) {
// 每个 key 对应一个 dep 集合
depsMap.set(key, (dep = new Set()))
}
if (!dep.has(activeEffect)) {
// 收集当前激活的 effect 作为依赖
dep.add(activeEffect)
// 当前激活的 effect 收集 dep 集合作为依赖
activeEffect.deps.push(dep)
}
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!