想品客老师的第四天:Set与WeakSet类型
Set
Set
对象允许你存储任何类型(无论是原始值还是对象引用)的唯一值。集合(set)中的元素只会出现一次,你可以按照插入顺序迭代集合中的元素。
声明set的方法
let set = new Set([1,2,3,4,5]);
set和array还有object的区别
set内对数据的唯一性的判断是严格模式判断,也就是说字符串'1'和数字1是不一样的
但是在对象里会被判定为一样,也就是字符串'1'和数字1是一样的:
let obj = {
1: "hdcms",
"1": "houdunren"
};
console.log(obj);//1:"houdunren"
同样的属性名会被后面的覆盖,所以打印不出前面的属性值
注意在对象里,如果属性名是一个对象的话,要加中括号
加中括号以后,对象名会被所属对象识别为一个字符串,所以此时想访问这个【对象里的对象】就需要在访问的时候把对象转为字符串:
let obj = {
1: "hdcms",
"1": "houdunren"
};
console.log(obj);
let hd = {
[obj]: "后盾人"
};
console.log(hd[obj.toString()]);
set储存的内容顺序:对于 add() 方法来说,就是调用 add()
方法时集合中不存在相同的元素的顺序,相同的就插不进去
let set = new Set();
set.add(1); // 成功插入 1
set.add(2); // 成功插入 2
set.add(1); // 1 已经存在,不会插入
set.add(3); // 成功插入 3
console.log(set); // 输出: Set { 1, 2, 3 }
Set元素检测与管理
set.size:返回set的大小
let set = new Set([1, 2, 3, 4, 5])
console.log(set.size)//5
set.has():判断是否有某个元素
let set = new Set([1, 2, 3, 4, 5])
console.log(set.has(1))//true
set.delete:删除元素,并且返回一个bool值,代表删除是否成功
let set = new Set([1, 2, 3, 4, 5])
console.log(set.delete(1))//true,删掉了
console.log(set.has(1))//false,没有1
console.log(set.size)//大小为4
set.values()也可以检测
console.log(set.values())//SetIterator {2, 3, 4, 5}
set.claer()清空元素,无返回值
console.log(set.clear())//清空,没有返回值,所以在这里打印为undefined
console.log(set.values())//SetIterator {}
set的类型转换
set转数组
有时候set在使用了数组方法时会进行隐式转换:
let set = new Set(["hdcms", "houdunren"]);
console.log(Array.from(set))//['hdcms', 'houdunren'],转换为数组
点语法也可以转换set为数组:
console.log([...set])//['hdcms', 'houdunren']
在对set进行一些操作的时候,把set变成数组再变回来也很方便:
let set = new Set("123456789")
console.log([...set])
set = new Set([...set].filter(function (item) {
return item < 5//筛选小于5的
}))
console.log(set)//Set(4) {'1', '2', '3', '4'}
可以简写为箭头函数:
let set = new Set("123456789")
set = new Set([...set].filter(item=> item < 5))
console.log(set)//Set(4) {'1', '2', '3', '4'}
数组转set
数组借用set去重:
let arr = [1, 2, 3, 4, 1, 2, 3, 4, 1]
arr = [...new Set(arr)]
console.log(arr)// [1, 2, 3, 4]
遍历set
set.keys()、set.values()、还有二者相结合的set.entries()
要注意的是对于 Set
来说,键和值是相同的,因为 Set
只存储值,没有键。
let set = new Set(["hdcms", "houdunren"]);
console.log(set.keys())//{'hdcms', 'houdunren'}
console.log(set.values())//{'hdcms', 'houdunren'}
console.log(set.entries())//{'hdcms' => 'hdcms', 'houdunren' => 'houdunren'}
所以这三个打印出来一样
set.forEach()
let set = new Set(["hdcms", "houdunren"]);
set.forEach(function (value, key, set) {
console.log(set);
})//hdcms,houdunren
for of():
let set = new Set(["hdcms", "houdunren"]);
for (const value of set) {
console.log(value);
}//hdcms,houdunren
demo:使用set处理关键词
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>后盾人</title>
<style>
body {
padding: 200px;
}
ul {
list-style: none;
padding: 0;
margin: 0;
width: 200px;
}
li {
border: solid 1px #ddd;
padding: 10px;
}
li:nth-of-type(odd) {
background: yellowgreen;
}
</style>
</head>
<body>
<input type="text" name="hd" />
<ul></ul>
</body>
<script>
let obj = {
data: new Set(),
keyword(word) {
this.data.add(word);
},
show() {
let ul = document.querySelector("ul");
ul.innerHTML = "";
this.data.forEach(function(value) {
ul.innerHTML += `<li>${value}</li>`;
});
}
};
let input = document.querySelector("[name='hd']");
input.addEventListener("blur", function() {
obj.keyword(this.value);
obj.show();
});
</script>
</html>
可以根据显示的关键词,记录搜索次数最多的,称为网络热门关键词
set的并集、交集、差集算法
set1内是用户1学习的科目,set2内是用户2学习的科目,如何求他们的公共学习科目?
并集算法,使用展开运算符将这个两个set合并,合并返回的set是没有重复部分的:
let set1 = new Set([1, 2, 3, 4, 5])
let set2 = new Set([1, 2, 4, 6, 9])
console.log(new Set([...set1, ...set2]));
但是这样有些1用户学习2用户不学习的科目也在里面了
可以通过这个方式获取set1和set2的公共部分
let set1 = new Set([1, 2, 3, 4, 5])
let set2 = new Set([1, 2, 4, 6, 9])
console.log(new Set(
[...set1].filter(function (item) {
return set2.has(item)
})
));
也就是交集算法
前面加个感叹号就是差集:
let set1 = new Set([1, 2, 3, 4, 5])
let set2 = new Set([1, 2, 4, 6, 9])
console.log(new Set(
[...set1].filter(function (item) {
return !set2.has(item)
})
));
相对于set1减去和set2的公共部分
WeakSet
WeakSet和set一样,也不能有重复的内容,而WeakSet是给引用类型用的set
前面学的给set的方法,WeakSet也可以用
let nodes = new WeakSet();
let divs = document.querySelectorAll("div");
divs.forEach(function (item) {
nodes.add(item);
});
nodes.delete(divs[0]);
console.log(nodes.has(divs[0]));//false
console.log(nodes);//WeakSet {div, div}
引用类型的垃圾回收原理
这个这篇讲过👇
WeakSet弱引用特性
垃圾回收机制里提到引用类型,用一次计数加1
而weakSet不会:
let hd = { name: "后盾人" };
let edu = hd;
let set = new WeakSet();
set.add(hd);
上面的代码可以看见hd、edu、set都指向了【name:'后盾人'】,说明引用次数应该记为3
但是WeakSet是弱引用,他引用了跟没引用一样,此时计数仍为2
而且不光这么离谱,当hd=null,edu=null,也就是引用计数为0的时候,会垃圾回收,【name:'后盾人'】就被清空了,但是即使清空了,也不告诉WeakSet
let hd = { name: "后盾人" };
let edu = hd;
let set = new WeakSet();
set.add(hd);
hd = null;
edu = null;
console.log(set)
能打出来,但什么都没有,weakSet以为里面应该有值,实际上什么都没有了
(你可以回来,但那里已经没有人了)
这种特性很容易在循环遍历的时候出问题,所以WeakSet禁用了很多循环遍历的方法,比如keys、values、entries
也会在获取大小的时候出问题,所以size方法也用不了
这种特性也导致在实行dom操作的时候,不用额外再去删weakset
WeakSet应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>后盾人</title>
</head>
<style>
* {
padding: 0;
margin: 0;
}
body {
padding: 100px;
}
ul {
list-style: none;
display: flex;
width: 200px;
flex-direction: column;
}
li {
height: 30px;
border: solid 2px #e67e22;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 10px;
color: #333;
transition: 1s;
}
a {
border-radius: 3px;
width: 20px;
height: 20px;
text-decoration: none;
text-align: center;
background: #16a085;
color: white;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
margin-right: 5px;
}
.remove {
border: solid 2px #eee;
opacity: 0.8;
color: #eee;
}
.remove a {
background: #eee;
}
</style>
<body>
<ul>
<li>houdunren.com <a href="javascript:;">x</a></li>
<li>hdcms.com <a href="javascript:;">x</a></li>
<li>houdunwang.com <a href="javascript:;">x</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 => {
const parentElement = event.target.parentElement;
if (this.lists.has(parentElement)) {
parentElement.classList.add("remove");
this.lists.delete(parentElement);
} else {
parentElement.classList.remove("remove");
this.lists.add(parentElement);
}
});
});
}
}
new Todo().run();
</script>
</html>
原文地址:https://blog.csdn.net/Au_ust/article/details/145292440
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!