Set的基本使用
ES6之前,我们存储数据的结构主要有两种:数组、对象。在ES6中新增了另外两种数据结构:Set、Map,以及它们的另外形式WeakSet、WeakMap。
- Set是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复。(也就是集合)
- 创建Set我们需要通过Set构造函数(暂时没有字面量创建的方式)
- 我们可以发现Set中存放的元素是不会重复的,那么Set有一个非常常用的功能就是给数组去重
Set的案例
Set的基本演示
const set = new Set()
set.add(10)
set.add(20)
set.add(25)
console.log(set); //Set(3) { 10, 20, 25 }
功能:数组去重
//功能1:数组去重
//注意:请不要这要做,这要set存进去的会是整个数组
let arr = [11,11,22,33,22,66,54]
// const set2 = new Set()
// set2.add(arr) //这样是错的
//我们可以在创建构造函数的时候把数组穿进去
const set2 = new Set(arr)
console.log(set2); //Set(5) { 11, 22, 33, 66, 54 }
//再利用数组的展开运算符将set变为数组
const newArr = [...set2]
console.log(newArr); //[ 11, 22, 33, 66, 54 ]
Set的属性
//我们可以在创建构造函数的时候把数组穿进去
const set2 = new Set(arr)
console.log(set2); //Set(5) { 11, 22, 33, 66, 54 }
//再利用数组的展开运算符将set变为数组
const newArr = [...set2]
console.log(newArr); //[ 11, 22, 33, 66, 54 ]
//set的size属性
console.log(set2.size); //5
//set的add属性
set2.add(34)
console.log(set2); //Set(6) { 11, 22, 33, 66, 54, 34 }
//set的delete属性(注意!必须传元素!不支持index)
set2.delete()
//判断某元素是否在set中存在
console.log(set2.has(34)); //true
//清空set
set2.clear()
console.log(set2); //Set(0) {}
对Set进行遍历
//上面代码的set2
set2.forEach(item =>{
console.log(item); //遍历set的每个元素
})
for(const item of set2){
console.log(item); //和forEach遍历的一样的
}
Set中添加对象
const set = new Set()
const obj = {
name:'harry'
}
set.add({})
set.add(obj)
console.log(set); //Set(2) { {}, { name: 'harry' } }
WeakSet的作用
和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构。
和Set的区别
- WeakSet中只能存放对象类型,不能存放基本数据类型。
- WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收。(Set是强引用) 这玩意听起来十分抽象。
强引用是什么(Strong reference)
对象的引用在 JavaScript 中是强引用,也就是将一个引用对象通过变量或常量保存
时,那么这个变量或常量就是强引用,这个对象就不会被回收。
弱引用是什么(Weak reference)
如果对象若被弱引用所引用,则被认为是不可访问(或弱可访问)的,并因此可能在任何时刻被GC(垃圾回收器)回收。
通过一张图来理解
如果是强引用item,obj这个指针断了,但是item指针还指着上面(name:harry)那个对象,GC不会将上面那个对象回收。不懂的同学可以去看我之前写的垃圾回收期的文章。
但是如果是弱引用,那就不会了,它时刻都可能被GC回收,比如任何一个指针断了,对象都可能被回收。
WeakSet的运用
WeakSet在开发中几乎不会用,基本上只有写那种非常严谨的框架才会出现这个。
使用WeakSet注意点
WeakSet只有add,delete和has方法,没有clear() 同时要注意它只能add对象
const weakSet = new WeakSet()
//区别1.WeakSet只能存放对象类型
// weakSet.add(10) //报错
Map的使用
Map用于存储映射关系。
我们可以使用对象来存储映射关系,可实际上我们对象存储映射关系只能用字符串(ES6新增了Symbol)作为属性名(key),某些情况下我们可能希望通过其他类型作为key,比如对象,这个时候会自动将对象转成字符串来作为key。
像这种情况就是错的(js会把对象转换成字符串[object Object])
// const info = {
// [obj1]:"aaa",
// [obj2]:"bbb"
// };
// console.log(info); //{ '[object Object]': 'bbb' } 他只会转出字符串 'object'
//所以JS是不能用对象来作为key的。
那么我们可以Map
const obj1 = {
name:'harry'
}
const obj2 = {
name:'kobe'
}
const map = new Map()
map.set(obj1,"aaa")
map.set(obj2,"bbb")
console.log(map); //Map(2) { { name: 'harry' } => 'aaa', { name: 'kobe' } => 'bbb' }
//map添加基本数据类型以及数组
map.set(1,"ccc")
map.set([1,2,3,4,5],"ddd")
console.log(map);
let arr = [11,23,43,33,55,66]
//如果想要批量的给map传值,也可以用数组的形式,不过传的数组需要满足entries格式,也就是[[]]数组里面套数组这种用法
//map也可以传数组进去,但是它是由要求的要是entries,像下面这种
// const map2 = new Map([ [key,value],[key,value],[key,value] ])
const map2 = new Map([[obj1,"aaa"],[obj2,"bbb"],[2,"ccc"],[arr,"ddd"]])
console.log(map2);
//map常见的属性和方法
console.log(map2.size); //4
//set
map2.set("abc","eee")
//get(key) -> 获取value
console.log(map2.get("abc")); //eee
//has(key) -> 判断map中存不存在该key的元素
console.log(map2.has("abc")); //true
//delete(key)
map2.delete("abc") //删除,并返回true
//clear
// map2.clear() //清空map
//遍历map
map2.forEach((item,key)=>{
console.log(item,key);
})
//可以用for of并解构
for(const [key,value] of map2){
console.log(key,value);
}
WeakMap的使用
和Map最主要的差别还是在强引用和弱引用,这个和WeakSet类似。
let obj = {name:'obj1'}
//WeakMap和Map的区别一:
//强引用
const map = new Map()
map.set(obj,"aaa")
//弱引用
const weakMap = new WeakMap()
weakMap.set(obj,"aaa")
//2.区别二:不能使用基本类型
// weakMap.set(1,"ccc") 报错
//3.常见方法
//get
console.log(weakMap.get(obj));
//has方法
console.log(weakMap.has(obj));
//delete
console.log(weakMap.delete(obj));
//注意,weakMap是不能遍历的,toString方法没啥用
console.log(weakMap); //{ <items unknown> }
//forEach是没有的
WeakMap与Map相结合使用
const obj = {
name:'harry',
age:21
}
const info = {
address:'山东'
}
const map1 = new Map()
const map2 = new Map()
map1.set("objName",obj.name)
map1.set("objAge",obj.age)
map2.set("infoAddress",info.address)
const weakmap = new WeakMap()
weakmap.set(obj,map1)
weakmap.set(info,map2)
let temp = weakmap.get(obj).get("objName")
console.log(temp); //harry
WeakMap的应用场景
比如Vue3的响应式原理。这个在写完proxy文章后我会接着补充并更新的。