JavaScript ES(6-11)全版本语法 (八):Set

171 阅读4分钟

前提概要

上一篇编写的是ES6中的Symbol,链接:juejin.cn/post/701057… ,这次写的是ES6中Set的基本语法、应用场景和WeakSet,可能不是很全。如有不对的或者不准确的地方,欢迎大家提出😄,我也积极修改。下边开始正文:

src=http___inews.gtimg.com_newsapp_bt_0_13926369622_1000&refer=http___inews.gtimg.jpg

基本语法

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

生成 Set 实例

let s = new Set()

可以定义一个空的 Set 实例,也可以在实例化的同时传入默认的数据。

let s = new Set([1, 2, 3, 4])

注意:

初始化的参数必须是可遍历的,可以是数组或者自定义遍历的数据结构。

添加数据

add()添加某一元素到 Set 数组当中

let s = new Set([1, 2, 3, 2])
s.add('xs').add('es6')
console.log(s) // Set(5) {1, 2, 3, 'xs', 'es6'}

注意:

Set 数据结构不允许数据重复,所以添加重复的数据是无效的

删除数据

delete()删除 Set 数组当中某一元素

let s = new Set([1, 2, 3, 2])
s.delete(2)
console.log(s) // Set(4) {1, 3, 'xs', 'es6'}

clear()清除 Set 数组当中所有的元素

let s = new Set([1, 2, 3, 2])
s.clear()
console.log(s) // Set(0) {}

统计数据

has()判断 Set 数组当中是否有某一个元素,返回boolean类型

let s = new Set([1, 2, 3, 2])
s.add('xs').add('es6')
console.log(s.has('xs')) // true
console.log(s.has('sx')) // false

size获取当前 Set 数组的内元素的个数

let s = new Set([1, 2, 3, 2])
console.log(s.size) // 3

遍历

  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每个成员
  • for...of:可以直接遍历每个成员
let s = new Set([1, 2, 3, 2])
s.add('xs').add('es6')

for (let item of s.keys()) {
  console.log(item) // 1 2 3 xs es6
}

for (let item of s.values()) {
  console.log(item) // 1 2 3 xs es6
}

for (let item of s.entries()) {
  console.log(item[0], item[1]) // 1 1  2 2  3 3  xs xs  es6 es6
}

s.forEach(item => console.log(item)) // 1 2 3 xs es6

for (let item of s) {
  console.log(item) // 1 2 3 xs es6
}

通过上述遍历可以看出,Set数组是有key和value的,但Set数组的key和value是相同的

应用场景

1、数组去重

let arr = [1, 2, 3, 4, 5, 6, 5, 7, 8, 1]
let s = new Set(arr)
console.log(s) // Set(8) {1, 2, 3, 4, 5, 6, 7, 8}

2、数组的合并去重

let arr1 = [1, 2, 3, 4, 5]
let arr2 = [2, 3, 4, 5, 6, 7, 8]
let s = new Set([...arr1, ...arr2])
console.log(s) // Set(8) {1, 2, 3, 4, 5, 6, 7, 8}

需求:数组合并去重后还是数组

let arr1 = [1, 2, 3, 4, 5]
let arr2 = [2, 3, 4, 5, 6, 7, 8]
let s = new Set([...arr1, ...arr2])
console.log([...s]) // [1, 2, 3, 4, 5, 6, 7, 8]
console.log(Array.from(s)) // [1, 2, 3, 4, 5, 6, 7, 8]

3、交集

let arr1 = [1, 2, 3, 4, 5]
let arr2 = [2, 3, 4, 5, 6, 7, 8]
let s1 = new Set(arr1)
let s2 = new Set(arr2)
let result = new Set(arr1.filter(item => s2.has(item)))
console.log(result) // Set(4) {2, 3, 4, 5}
console.log(Array.from(result)) // [2, 3, 4, 5]

4、差集

let arr1 = [1, 2, 3, 4, 5]
let arr2 = [2, 3, 4, 5, 6, 7, 8]
let s1 = new Set(arr1)
let s2 = new Set(arr2)
let s3 = new Set(arr1.filter(item => !s2.has(item)))
let s4 = new Set(arr2.filter(item => !s1.has(item)))
console.log(s3) // Set(1) {1}
console.log(s4) // Set(3) {6, 7, 8}
// 把差集合并成一个数组
console.log([...arr3, ...arr4]) // [1, 6, 7, 8]

WeakSet

WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。

WeakSet 的成员只能是对象,而不能是其他类型的值。

const ws = new WeakSet()
ws.add(1)
// Uncaught TypeError: Invalid value used in weak set
ws.add(Symbol())
// Uncaught TypeError: Invalid value used in weak set
let ws = new WeakSet()
const obj1 = {
    name: 'xs'
}
const obj2 = {
    age: 18
}
ws.add(obj1) 
console.log(ws) // WeakSet {{…}}
ws.add(obj2) 
console.log(ws) // WeakSet {{…}, {…}}
ws.delete(obj1) 
console.log(ws) // WeakSet {{…}}
console.log(ws.has(obj2)) // true

遍历

WeakSet 没有size属性,没有办法遍历它的成员。

ws.forEach(item => console.log(item)) 
// Uncaught TypeError: ws.forEach is not a function

上述代码,证明 WeakSet 类型不允许遍历

注意:

WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。

垃圾回收机制 GC(仅概念)

垃圾回收机制运用的是计数的垃圾回收机制,意思假如当前我定一个值,这个值被引用一次,那么这个次数就加一,只要当前被引用的值不为零,那么垃圾回收机制就不会回收这个变量,也就是说不会释放当前这个内存空间

使用场景

比如说临时存放对象或者跟对象绑定一些相关信息

Set和WeakSet的区别

  1. Set可以存储任意数据类型,WeakSet只能存储对象
  2. Set可以循环遍历,WeakSet是不可以遍历的
  3. WeakSet是一种弱引用,不会被垃圾回收机制考虑,所以说,它里面引用的对象,如果对象消失以后,那么WeakSet内的引用也会自动消失