ES6新增数据结构Set与Map(包括WeakMap/Set等)

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的区别

  1. WeakSet中只能存放对象类型,不能存放基本数据类型。
  2. WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收。(Set是强引用)
    这玩意听起来十分抽象。
强引用是什么(Strong reference)

对象的引用在 JavaScript 中是强引用,也就是将一个引用对象通过变量或常量保存时,那么这个变量或常量就是强引用,这个对象就不会被回收。

弱引用是什么(Weak reference)

如果对象若被弱引用所引用,则被认为是不可访问(或弱可访问)的,并因此可能在任何时刻被GC(垃圾回收器)回收。

通过一张图来理解

image.png

如果是强引用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的应用场景

比如Vue3的响应式原理。这个在写完proxy文章后我会接着补充并更新的。

来自本人掘金:https://juejin.cn/post/7114111935808798728/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值