JS - 6 - Set 和 WeakSet - 弱引用
程序员文章站
2022-05-20 14:57:02
...
文章目录
Set
Set
对象是 ES6
新增,特点:元素不重复。
# 不可重复
let set = new Set([1,1,2]); // 不可重复
console.log(set) ;
# 区分类型
let set = new Set([1,'1',2]); // 不可重复
console.log(set)
# 构造函数传字符串
let set = new Set("abc");// 等于 new Set([..."abc"])
console.log(set)
所以 , 我们传字符串 ,需要(下面)
let set = new Set(["abc","bbb"]);
console.log(set)
# API
转载: https://blog.csdn.net/wuyujin1997/article/details/88741351
-
size
集合大小 -
add(value)
- Set 添加元素。(可链式编程) -
has(value)
- boolean 查询元素是否存在。 -
delete(value)
- boolean 删除 -
clear()
- 清空 -
forEach(callback)
- 对容器内每个元素做操作。(下面) -
keys()
- 用法同values(),因为set只有value列表。 values()
-
entries()
- 不推荐。会返回两倍的set(见代码)。
# 类型转换
## 转换成数组
let set = new Set(['aaa','bbb']);
console.log(Array.from(set));
console.log([...set])
## 转换成数组 - 应用1
// 取 n 中小于5 的数(不重复)
let n = '12342345242323';
let hd = new Set(n) ;
let set = new Set([...hd].filter(item => item<5)) ;
console.log(set)
## 转换成数组 - 应用2
去重
let array = [1,1] ;
array = [... new Set(array)] ;
console.log(array)
# 遍历
## values、keys、entries
就那样
## forEach
let set = new Set(['aa' , 'bb']) ;
set.forEach((value, key, set) => {
console.log(value, key, set) ;
})
## for of
let set = new Set(['aa' , 'bb']) ;
for(const value of set ) {
console.log(value) ;
}
# 案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<input type="text" name="hd">
<ul></ul>
<body>
<script>
let obj = {
data: new Set() ,
set keyword(word) {
this.data.add(word) ;
},
show() {
let ul = document.querySelector('ul');
ul.innerHTML='' ;
this.data.forEach(value => {
ul.innerHTML+=`<li>${value}</li>`;
})
}
}
let input = document.querySelector(`[name='hd']`) ;
input.addEventListener('blur', function() {
obj.keyword = this.value ;
obj.show() ;
})
</script>
</body>
</html>
# 并集、差集、交集 - 处理
let a = new Set([1,2]) ;
let b = new Set([2,5]) ;
console.log(new Set([...a, ...b])) // 并集
console.log(// 差集合 A中不包含B
new Set(
[...a].filter((value) => {
return !b.has(value);
})
)
)
console.log(// 交集
new Set(
[...a].filter(value => b.has(value))
)
)
文章目录
WeakSet
# 只能添加引用类型
let arr = ['aa', 'bb'] ;
// let set = new WeakSet(arr) ; 会报错
let set = new WeakSet() ;
// set.add(arr[0]); 会报错
set.add(arr) ;
console.log(set) ;
# 基本用法
api 基本用法和 set 一样,只有如下 api:
add
delete
has
(为什么,只有这么点 api? 下面说)
主要,WeakSet 只能保存引用类型!
let nodes = new WeakSet() ;
let divs = document.querySelectorAll('div');
divs.forEach(item => {
nodes.add(item) ;
})
console.log(nodes)
nodes.delete(divs[0]) ; // 删除
console.log(nodes)
console.log(nodes.has(divs[1])) // 判断有误
# 特点:弱引用
Set 他不香吗,为什么要用 WeakSet?
## 引入 “垃圾回收” 概念
当没有引用,数据会被视为垃圾,被回收
let hd = {name:'后盾人'}; // 引用 +1
let edu = hd ; // 引用 +1
hd = null ;// 引用 -1
edu = null ; // 引用 -1
// {name:'后盾人'} ==> 被(垃圾)回收
## 弱引用
引用数据,数据的引用数不加1,即为弱引用
-
使用弱引用
let hd = {name:'后盾人'}; // 引用 +1 let edu = hd ; // 引用 +1 let set = new WeakSet() ; set.add(hd) ; // 引用 +0 console.log(set)
-
清除强引用
let hd = {name:'后盾人'}; // 引用 +1 let edu = hd ; // 引用 +1 let set = new WeakSet() ; set.add(hd) ; // 引用 +0 console.log(set) edu = null ; // 引用 -1 hd = null ; // 引用 -1
可以看到,强引用清除后,弱引用的数据不会保留
这导致 无法循环、遍历(下图)
let set = new WeakSet() ;
set.keys();
let set = new WeakSet() ;
for (const i of set) {}
甚至无法使用 size 属性 ( 下图 )
let set = new WeakSet() ;
console.log( set.size ) ;
# 案例
看了 弱引用,第一眼的感觉是 “鸡肋”
那么,它存在的必要性是什么?
这篇知乎文章说了:《WeakSet 用法解惑》 - https://zhuanlan.zhihu.com/p/54889129
引用的原始文章:《ECMAScript 6: what is WeakSet for? 》 - https://*.com/questions/30556078/ecmascript-6-what-is-weakset-for
弱引用作用:一个集合,既要判断集合元素,又不想管理集合元素的声明周期,弱引用就是必要的。
下面的案例:
有两个独立的功能:
- 删除集合元素(生命管理)
- 判断集合元素,作出对应决策
<!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>
ul>li{
width: 300px;
background: green;
}
ul li a {
width: 60px;
display: inline-block;
text-align: center;
background: yellow;
}
.remove{
background: red;
}
</style>
</head>
<ul>
<li>https://houdunren.com <a href="javascript:;">删除</a></li>
<li>hdcms.com <a href="javascript:;">删除</a></li>
<li>houdunwang.com <a href="javascript:;">删除</a></li>
</ul>
<body>
<script>
class Todo {
constructor() {
this.items = document.querySelectorAll("ul>li")
this.lists = new WeakSet() ;
this.items.forEach(item => {
this.lists.add(item) ;
})
}
run() {
this.addEvent() ;
}
addEvent() {
this.items.forEach(item => {
let a = item.querySelector('a') ;
a.addEventListener('click', event => {
// 给a的父级加样式
const parentElement = event.target.parentElement ;
if(this.lists.has(parentElement)) {
parentElement.classList.add('remove') ;
this.lists.delete(parentElement) ;
} else {
if(confirm('已删除,想要恢复?')) {
parentElement.classList.remove('remove');
this.lists.add(parentElement)
}
}
})
})
}
}
new Todo().run() ;
</script>
</body>
</html>
get?