ES6提供了新的数据结构Set,Set对象不是数组, 可以用来保存对象或者基本类型, 所有保存的值都是唯一的, chrome浏览器>38和FF>13,以及nodeJS,对Set支持良好。
1.Set类型对象的声明;Set类型与Array与Object对比分析
可以在声明set类型时赋值,也可以使用add向set中添加元素。
let s1 = new Set()
s1.add(1)
console.log(s1)// Set(1) {1}
let s2 = new Set([1,2,3,4,5])
console.log(s2)// Set(5) {1, 2, 3, 4, 5}
set类型不允许存在相同的元素,并且为严格类型约束。
let s1 = new Set()
s1.add(1)
s1.add("1")
console.log(s1)// Set(2) {1, "1"}
但是在对象中并非严格类型约束,它会将数字类型转换为字符串类型。
let obj1 = {
1:'weizhuren',
"1":'erbihouke'
}
console.log(obj1)// {1: "erbihouke"}
2.set元素检测与管理
- 使用size方法可以检测set的大小(长度),返回值为大小(长度)
- has方法判断set是否包含该元素,返回一个布尔类型的值,包含返回true,不包含返回fasle,如果判断的元素为其中一个元素的一部分,也返回false
let s1 = new Set("123456789")
console.log(Array.from(s1))
console.log(...s1)
let arr = [...s1].filter( i => i < 5)
console.log(arr)
console.log(new Set(arr))
- delete方法可以删除对应元素,删除成功返回true,删除失败返回false
- values方法可以查看set的值
- clear方法清空set,无返回值
let s1 = new Set(['weizhuren','erbihouke'])
console.log(s1.size)// 2
console.log(s1.has('weizhuren'))// true
console.log(s1.has('wei'))// false
console.log(s1.delete('erbihouke'))// true
console.log(s1.values())// SetIterator {"weizhuren"}
s1.clear()
console.log(s1)// Set(0) {}
3.类型之间的相互转换
set类型类型转化为数组,使用array.from方法和展开语法都可以直接转化为数组,使用new Set方法可以将数组转换为set:
let s1 = new Set("123456789")
console.log(Array.from(s1))// ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
console.log(...s1)// ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
let arr = [...s1].filter( i => i < 5)
console.log(arr)// ["1", "2", "3", "4"]
console.log(new Set(arr))// Set(4) {"1", "2", "3", "4"}
既然可以相互转换,我们就可以李用不同类型的性值,来处理数据,下面我们使用set类型的性值为数组去重:
因为set类型不允许存在相同的元素,所以可以将数组转换为set类型然后再转换为数组,这样就可以去重了。
let arr = [1,2,3,4,5,6,4,2,5,1]
arr = [...new Set(arr)]
console.log(arr)// [1, 2, 3, 4, 5, 6]
4.遍历set类型的方式
set可以使用forEach方法遍历,使用forEach遍历set的时候,同样也有三个参数:value(元素值),key(元素的键),set(set本身),由于set类型没有key,所以key值和value值相同。
let s1 = new Set(['weizhuren','erbihouke'])
s1.forEach( (item,key,set) => console.log(item,key,set))
//weizhuren weizhuren Set(2) {"weizhuren", "erbihouke"}
//erbihouke erbihouke Set(2) {"weizhuren", "erbihouke"}
也可以使用for···of对set进行遍历。
for (const item of s1) {
console.log(item)
}
// weizhuren
// erbihouke
5.使用set处理网站关键词
我们利用set的性质,当用户在输入框输入内容并且输入框失去焦点时,记录这些内容。
我们定义一个对象,定义一个set类型的data和一个向ul中添加li标签的方法,在input失去焦点时,触发这个方法。由于使用的是set类型,所以失去焦点时不会将重复的添加相同内容的标签。
<body>
<input type="text" name="info">
<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(element => {
ul.innerHTML += `<li>${element}</li>`
});
},
}
let input = document.querySelector("[name='info']")
input.addEventListener('blur',function(){
obj.keyWord = this.value
obj.show()
})
</script>
6.并集-交集-差集实现算法
并集查看两个set对象都拥有的属性;交集查看两个set对象共同拥有的属性;差集查看a对象比b对象多的属性。
let a = new Set([1,2,3,4,5])
let b = new Set([4,3,6,7])
// 并集
console.log(new Set([...a,...b])) //{1, 2, 3, 4, 5, 6,7}
// 交集
console.log(new Set(new Set([...a].filter( item => b.has(item)))))// Set(2) {3, 4}
// 差集
console.log(new Set([...a].filter( item => !b.has(item))))// Set(3) {1, 2, 5}
7.WeakSet语法介绍
WeakSet和set类型一样,不允许有重复的值,并且WeakSet只能声明引用类型的值。
- WeakSet和set一样,可以在声明时赋值也可以使用add方法赋值
- 使用delete方法可以删除对应的项
- 使用has方法可以查询是否存在某一项
let s = new WeakSet()
s.add(["weizhuren","erbihouke"])
let nodes = new WeakSet()
let divs = document.querySelectorAll('div')
divs.forEach( item => {
nodes.add(item)
})
nodes.delete(divs[0])
console.log(nodes.has(divs[0]))// false
console.log(nodes)// WeakSet {div}
8.引用类型的垃圾回收原理
简单来说,一个变量再不被引用(使用)的以后,就会被系统回收。
9.WeakSet弱引用特性
WeakSet在引用对象的时候,并不会访问对象的地址,当引用的对象被删除(为null)后,系统仍然认为WeakSet有值(实际没有)。这个特性在IE浏览器中可以表现出来,但是在chrome浏览器中则没有,这需要继续学习。
当我们在使用弱引用类型(WeakSet,WeakMap)存储dom节点(或其他情况)时,dom节点的删除不会影响弱引用类型的使用,就是说当我们删除dom节点后,不用再去删除弱引用类型中的数据。
也是基于此特性,弱引用类型不能使用迭代等方法。