ES6 - Set & WeakSet

152 阅读3分钟

Set

介绍

  1. Set结构是es6中新的数据结构,类似数组,但是值都是唯一的,不重复,可以理解为set构造函数天生就会把我们传进去的数组进行去重。
  2. 拥有Iterator接口,支持for of
let set = new Set([1,3,5,5,6,6])
set // [1,3,5,6]
set.size // 4

Set实例的属性和方法

  1. 属性:拥有size属性,set.prototype.size 返回Set实例的成员总数。
  2. 方法:包括两类,操作方法和遍历方法。

操作方法

  • add(val) : 添加值,返回结构本身
  • delete(val) :删除某个值,返回一个布尔值,表示是否删除成功
  • has(val) : 返回一个布尔值,表示是否存在某个值
  • clear() : 清空数据,无返回值
set.add(1).add(3).add(3)

set.size // 2

set.has(1) // true
set.has(2) // false
set.delete(3) 
set.has(3) // false

遍历方法

拥有四个遍历方法,都差不多

  • keys() :返回一个包含键名的遍历器
  • values() : 返回键值的遍历器
  • entries() : 返回键值对的遍历器
  • forEach() : 和普通的forEach一样
let set = new Set(['a','b','c'])
for(let i of set.keys()){
  console.log(i)
}
// a
// b
// c
let set = new Set(['a','b','c'])
for(let i of set.entries()){
  console.log(i)
}
// ['a','a']
// ['b','b']
// ['c','c']

这里values和keys的效果一样,因为set结构不存在键值对,键就是值,值就是键,键和值是同一个值,并且根本不需要他来遍历set结构,直接for of 就可以,因为他的遍历器生成函数就是values方法

Set.prototype[Symbol.iterator] ==== Set.prototype.values

使用扩展运算符操作set

  • 扩展运算符(...)内部使用for...of循环,所以也可以用于 Set 结构。 阮一峰老师原话。

  • 数组的扩展中讲了,任何定义了遍历器(Iterator)接口的对象,都可以用扩展运算符转为真正的数组。操作一下:

let set = new Set(['a','b','c','c'])
let arr  = [...set]     // [ 'a', 'b', 'c' ]
console.log(Array.isArray(arr)); // true
通过扩展运算符,实现数组去重
  • 这三种也比较有用,实现交集、并集、和差集。
let a = new Set([1, 2, 5, 6])
let b = new Set([1, 2, 4, 6])

let union = new Set([...a, ...b])
console.log("TCL: union", union)  // TCL: union Set { 1, 2, 5, 6, 4 }

let intersect = new Set([...a].filter((e) => b.has(e)))
console.log("TCL: intersect", intersect)  // TCL: intersect Set { 1, 2, 6 }

let diff = new Set([...a].filter((e) => !b.has(e)))
console.log("TCL: diff", diff)  // TCL: diff Set { 5 }

  • 另外,遍历过程无法改变set的值,可以通过处理一个新的set再重新赋值的形式做到,比如利用map和Array.from()这两种返回新数组的方法实现。
let set = new Set([1,3,5])
set = new Set([...set].map( e => e*2))
// Set(3) {2, 6, 10}
set = new Set(Array.from(set, e => e*2))
// 结果一样

WeakSet

与Set区别

  1. WeakSet只能存对象
  2. WeakSet就像它的名字一样,WeakSet中的值都是弱引用的,什么是弱引用,弱引用又有什么用呢?
  • 弱引用就是垃圾回收不考虑WeakSet对对象的引用。因此我们可以利用弱引用的特性,存储一些动态的依赖数据,这样就可以不用主动去管理它,不引用的数据会自动被回收掉。
  1. WeakSet不能被遍历,没有size属性,可以进行添加、删除、has判断
    const b = [{ a: 1 }, { b: '2' }];
    const ws = new WeakSet(b);
    const obj = { c: 3 };
    ws.add(obj);
    console.log(ws);
    console.log(ws.has(obj));