在我们开始研究Vue3原理之前有一些前置知识这里先简单复习下,工欲善其事必先利其器嘛。

# Set

ES6中提供了Set这种数据结构,它类似数组,但成员值是唯一的,没有重复值。

# 创建

let s = new Set()

Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。

let s = new Set([3, 45, 5, 6, 'f', true])

# 常用方法

  • Set.prototype.add(value):添加某个值,返回 Set 结构本身。 可以通过add方法向Set结构中添加成员
let s = new Set()
s.add(1)

向Set中添加元素时不会发生类型转换,Set内部判断值是否相等使用的是“Same-value-zero equality”,类似于 ===,区别是Set认为NaNd等于自身,===认为NaN不等于自身,两个对象也是不等的。

  • Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
let s = new Set([3, 4, 5])
s.delete(3)
console.log(s) // Set(2) {4, 5}
  • Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员。
let s = new Set([3, 4, 5])
console.log(s.has(3)) // true
  • Set.prototype.clear():清除所有成员,没有返回值。
let s = new Set([3, 4, 5])
s.clear()
console.log(s) // Set(0) {}
  • Set.prototype.keys():返回键名的遍历器
  • Set.prototype.values():返回键值的遍历器 Set 结构没有键名,只有键值,所以keys方法和values方法的行为一致。
const s = new Set([3, 4, 5])
for (let item of s.keys()) {
  console.log(item);
}
/* 
3
4
5
*/

for (let item of s.values()) {
  console.log(item);
}
/*
3
4
5 
 */
  • Set.prototype.entries():返回键值对的遍历器
for (let item of new Set([3, 4, 5]).entries()) {
  console.log(item);
}
/* 
[3, 3]
[4, 4]
[5, 5]
 */
  • Set.prototype.forEach():使用回调函数遍历每个成员
new Set([3, 4, 5]).forEach((value, key) => console.log(key + ' : ' + value))
/* 
3 : 3
4 : 4
5 : 5
 */

注意:Set遍历时是按照插入顺序遍历的。

# 其他用途

去除数组中的重复元素

[...new Set(array)]

// or

function dedupe(array) {
  return Array.from(new Set(array));
}
dedupe([1, 1, 2, 3]) // [1, 2, 3]

去除字符串里的重复元素

[...new Set('ababbc')].join('')

求并集(Union)、交集(Intersect)和差集

let set1 = new Set([3, 4, 5]);
let set2 = new Set([5, 6, 7]);

// 并集
let union = new Set([...set1, ...set2]);

// 交集
let intersect = new Set([...set1].filter(x => set2.has(x)));

// 差集
let difference = new Set([...set1].filter(x => !set2.has(x)));

# WeakSet

WeakSet 的成员只能是对象,而不能是其他类型的值。WeakSet中的对象是弱引用,垃圾回收机制不考虑 WeakSet 对该对象的引用,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。WeakSet不可遍历,没有size属性。

# 创建

const ws1 = new WeakSet();

// 可以接受一个数组或类似数组的对象作为参数
const a = [[1, 2], [3, 4]];
const ws2 = new WeakSet(a);

// 数组b的成员不是对象,加入 WeakSet 会报错
const b = [3, 4];
const ws = new WeakSet(b); // Uncaught TypeError: Invalid value used in weak set(…)

# WeakSet的常用方法

  • WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。
  • WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。
  • WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例之中。

和上面Set的使用方式一样,这里不再列举。

# Map

# 常用属性和方法

  • size 属性返回 Map 结构的成员总数。
const map = new Map()
map.size // 0
  • Map.prototype.set(key, value), 设置键名key对应的键值为value,返回当前的Map对象
let map = new Map()
  .set(1, 'a')
  .set(2, 'b')
  .set(3, 'c');
  • Map.prototype.get(key)读取key对应的键值
let map = new Map()
map.get('name') // undefined
  • Map.prototype.has(key)返回一个布尔值,表示某个键是否在当前 Map 对象之中
let map = new Map()
map.has('name') // false
  • Map.prototype.delete(key)删除某个键,成功返回true。如果删除失败,返回false
let map = new Map()
map.delete('name') // false
  • Map.prototype.clear()清除所有成员,没有返回值。
let map = new Map()
map.clear()
  • Map.prototype.keys():返回键名的遍历器。

  • Map.prototype.values():返回键值的遍历器。

  • Map.prototype.entries():返回所有成员的遍历器。

  • Map.prototype.forEach():遍历 Map 的所有成员。

# WeakMap

WeakMap的键名所引用的对象都是弱引用,垃圾回收机制不将该引用考虑在内,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。

WeakMap与Map的区别:

  1. WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名
  2. WeakMap的键名所指向的对象,不计入垃圾回收机制。

参考:

Set 和 Map 数据结构 (opens new window)

Proxy (opens new window)

Reflect (opens new window)