头图

在JavaScript中,Set和WeakSet都是ES6引入的新的数据结构。(称其为集合)

1.简介

Set:

  • Set类似于数组,可以存储任何类型的唯一值(无重复),包括基本类型和复杂类型。
  • 可以使用new Set()构造函数创建一个Set。
  • 可以使用add()方法向Set添加元素。
  • 可以使用delete()和clear()方法从Set中移除元素。
  • 可以使用for...of循环或forEach()方法遍历Set的元素。
    WeakSet:
  • WeakSet只能包含对象,不能像Set那样包含任何类型的值。
  • WeakSet内的引用对对象是弱引用。如果没有其他对WeakSet中对象的引用存在,那么这些对象会被垃圾回收(即,WeakSet不是对象的强引用,并且不会阻止垃圾回收)
  • WeakSet不可迭代,也就是说不能用for...of循环遍历它的元素
  • WeakSet没有size属性,也没有clear、keys、values、entries、forEach等方法

2.Set基本使用

1.使用数组赋值:

let hd = new Set(['零跑c10', '银河L7']);
console.log(hd.values()); //{"零跑c10", "银河L7"}

2.Set 中是严格类型约束的,下面的数值1与字符串1属于两个不同的值

let set = new Set();
set.add(1);
set.add("1");
console.log(set); //Set(2) {1, "1"}

3.使用 add 添加元素,不允许值重复

let hd = new Set();
hd.add('1');
hd.add('2');
hd.add('2')

console.log(hd); 

4.获取元素数量

let hd = new Set(['1', '2']);
console.log(hd.size); //2

5.检测元素是否存在

let setVal = new Set();
setVal.add(1);
console.log(setVal.has(1));//true

6.删除元素
使用delete删除元素

let setVal = new Set();
setVal.add(1);
setVal.add(2);
setVal.add(3);
setVal.delete(2);
console.log(setVal);//Set(2) {1, 3}

console.log(setVal.delete(123));//false

使用clear删除Set中的全部

let setVal = new Set();
setVal.add(1);
setVal.add(2);
setVal.add(3);

setVal.clear();
console.log(setVal);//Set(0) {size: 0}

3.Set使用场景举例

1.可以将Set转为数组,使用数组的方法
例如:去掉Set中小于3的元素

let setVal = new Set();
setVal.add(1);
setVal.add(2);
setVal.add(3);

setVal = [...setVal].filter(item => {
    return item > 2;
});

console.log(setVal);[3]

2.Set值不能重复,所有可以利用这个特性对数组进行去重操作
例入:

let arr = [1,2,3,3,2,1,67,67,99];
arr = new Set(arr);
arr = [...arr];
console.log(arr);//[1, 2, 3, 67, 99]

3.还是利用Set值唯一这个特点,如果页面中需要输入不唯一的值,保存的方式可以不使用数组,而使用集合Set
例如:将每次输入的值,鼠标失去焦点后如果不存在则显示在屏幕上:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            padding: 200px;
        }
      
        * {
            padding: 0;
            margin: 0;
        }
      
        ul {
            list-style: none;
            width: 200px;
            padding-top: 20px;
        }
      
      </style>
</head>
<body>
    <input type="text">
    <ul></ul>
  </body>
  <script>
    let obj = {
        words: new Set(),
        set keyword(word) {
            this.words.add(word);
        },
        show() {
            let ul = document.querySelector('ul');
            ul.innerHTML = '';
            this.words.forEach((item) => {
                ul.innerHTML += ('<li>' + item + '</li>');
            })
        }
    }
  
    document.querySelector('input').addEventListener('blur', function () {
        console.log('打印this', this);
        obj.keyword = this.value;
        obj.show();
    });
  </script>
4.交集,并集,差集
    let a = new Set([1,2,3]);
    let b = new Set([3,4,5]);
    
    //交集
    let c = [...a].filter(item => b.has(item));
    console.log(c);

    //并集
    let d = new Set([...a,...b]);
    console.log(d);

    //差集
    let e = [...a].filter(item => !b.has(item));e
    console.log(e);

4.Set和Array查找元素时性能问题

在JavaScript中,Set和Array的主要区别在于它们内部数据的组织方式。
首先,我们来看一下如何在Array中查找元素:

let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // 创建一个数组
let index = array.indexOf(7); // 查找元素7在数组中的位置
console.log(index); // 输出:6

在上面的代码中,我们使用indexOf方法在数组中查找元素7。这个方法会从头到尾遍历数组,直到找到元素7,所以时间复杂度为O(n)。

对于Array,它是一个线性数据结构,也就是说,它的元素是按照插入的顺序一个接一个地存储的。当我们需要查找一个元素时,我们需要从头到尾遍历数组直到找到该元素。因此,最坏的情况是我们需要遍历整个数组,所以查找元素的时间复杂度为O(n),其中n是数组的长度。

接下来,我们来看一下如何在Set中查找元素:

let set = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); // 创建一个Set
let hasSeven = set.has(7); // 查找Set中是否包含元素7
console.log(hasSeven); // 输出:true

我们使用has方法在Set中查找元素7。由于Set内部使用哈希表来存储数据,所以查找元素的时间复杂度接近O(1),这比在Array中查找元素要快得多。
对于Set,它是基于哈希表(Hash Table)的数据结构。哈希表是一种可以实现近乎O(1)时间复杂度查找的数据结构。当我们插入一个元素时,Set会使用一个哈希函数将该元素映射到哈希表的一个位置。当我们需要查找一个元素时,Set只需要查找该元素对应的哈希值在哈希表中的位置,而不需要遍历整个集合。因此,查找元素的时间复杂度接近O(1)。
虽然在某些情况下,Array可以替代Set,但是Set在元素查找和确保元素唯一性方面具有优势。我个人感觉除非需要保存重复数据时候,其余场景完全可以使用Set代替Array,因为Set可以完全使用Array的方法,并且查找起来也更加的方便。

4.WeakSet基本使用

1.声明定义

WeakSet值必须是对象类型
new WeakSet([["1,2"], ["3"]]);
DOM节点也可以保存在WeakSet

let Wset = new WeakSet();
document.querySelectorAll("button").forEach(item => Wset.add(item));
2.基本指令
const hd = new WeakSet();
const arr = ["1"];
//添加操作
hd.add(arr);
console.log(hd.has(arr));

//删除操作
hd.delete(arr);

//检索判断
console.log(hd.has(arr));
3.垃圾回收

引用类型垃圾回收原理简单说就是没人使用的情况下就将其删除

将数组放在WeakSet中,就是弱引用;
也就是说引用计数器不会叠加,请看下面这个例子:

const WSet = new WeakSet();
let arr = ["劳动节"];
WSet.add(arr);
console.log('WeakSet', WSet.has(arr));

arr = null;
console.log('After arr = null',WSet); //WeakSet {Array(1)}

setTimeout(() => {
  console.log('1s after WeakSet',WSet); //WeakSet {}
}, 1000);

可以发现,当我将数组arr 置为 null 后,外部不在使用arr了,当垃圾回收时对象被删除,这时WakeSet也就没有记录了。
也是因为这个特性,会导致WeakSet有可能保存系统还没来的及删除的垃圾数据,所以WeakSet没有keys(),循环这些操作。


豪爽和龙虾
1 声望0 粉丝