在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(),循环这些操作。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。