title: set/map
categories: Javascript
tag:
- set/map
date: 2021-11-27 09:16:34
set 的基本使用
在 ES6 之前,我们存储数据的结构主要有两种:数组、对象。
- 在 ES6 中新增了另外两种数据结构:Set、Map,以及它们的另外形式 WeakSet、WeakMap。
Set 是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复。
- 创建 Set 我们需要通过 Set 构造函数(暂时没有字面量创建的方式):
我们可以发现 Set 中存放的元素是不会重复的,那么 Set 有一个非常常用的功能就是给数组去重。
const set1 = new Set()
set1.add(10)
set1.add(20)
set1.add(30)
set1.add(40)
set1.add(40)
//元素不会重复
console.log(set1) //Set(4) { 10, 20, 30, 40 }
但是如果是对象的话
set1.add({})
set1.add({})
console.log(set1) //Set(6) { 10, 20, 30, 40, {}, {} }
但是我们写为如下形式
//但是如果我们写为这个形式,就只会出现一次啦
const obj = { 1: '1' }
set1.add(obj)
set1.add(obj)
console.log(set1) //Set(7) { 10, 20, 30, 40, {}, {}, { '1': '1' } }
Set 中存放的元素是不会重复的。那么 Set 有一常用的功能就是给数组去重
const arr = [10, 20, 30, 40, 30, 20]
const arrSet = new Set(arr)
console.log(arrSet) //Set(4) { 10, 20, 30, 40 }
const newArr = [...arrSet]
console.log(newArr) //[ 10, 20, 30, 40 ]
set 常见方法
Set 常见的属性:
- size:返回 Set 中元素的个数;
Set 常用的方法:
- add(value):添加某个元素,返回 Set 对象本身;
- delete(value):从 set 中删除和这个值相等的元素,返回 boolean 类型;
- has(value):判断 set 中是否存在某个元素,返回 boolean 类型;
- clear():清空 set 中所有的元素,没有返回值;
- forEach(callback, [, thisArg]):通过 forEach 遍历 set;
另外 Set 是支持 for of 的遍历的。
for (const item of set1) {
console.log(item)
}
WeakSet 使用
和 Set 类似的另外一个数据结构称之为 WeakSet,也是内部元素不能重复的数据结构。
那么和 Set 有什么区别呢?
- 区别一:WeakSet 中只能存放对象类型,不能存放基本数据类型;
- 区别二:WeakSet 对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么 GC 可以对该对象进行回收;
const wset = new WeakSet()
//区别1:不能存放基本数据类型
wset.add(10) //TypeError: Invalid value used in weak set
console.log(wset)
let obj = {
name: 'why'
}
//建立的是弱引用
wset.add(obj)
console.log(wset) //WeakSet { <items unknown> }
WeakSet 应用场景
注意:WeakSet 不能遍历
- 因为 WeakSet 只是对对象的弱引用,如果我们遍历获取到其中的元素,那么有可能造成对象不能正常的销毁。
- 所以存储到 WeakSet 中的对象是没办法获取的;
那么这个东西有什么用呢?
- 事实上这个问题并不好回答,我们来使用一个 Stack Overflow 上的答案;
Map
Map 的基本使用
另外一个新增的数据结构是 Map,用于存储映射关系。
- 但是我们可能会想,在之前我们可以使用对象来存储映射关系,他们有什么区别呢?
- 事实上我们对象存储映射关系只能用字符串(ES6 新增了 Symbol)作为属性名(key);
const obj1 = { name: 'why' }
const obj2 = { age: 18 }
const info = {
[obj1]: 'aaa',
[obj2]: 'bbb'
}
console.log(info) //{ '[object Object]': 'bbb' }
对象类型会转换为[object Object]
,因此就只能是这一个。
- 某些情况下我们可能希望通过其他类型作为 key,比如对象,这个时候会自动将对象转成字符串来作为 key;
那么我们就可以使用 Map:
const obj1 = { name: 'why' }
const obj2 = { age: 18 }
const map = new Map()
map.set(obj1, 'abc')
map.set(obj2, 'cba')
console.log(map) //Map(2) { { name: 'why' } => 'abc', { age: 18 } => 'cba' }
创建 Map 的方式
const map1 = new Map([
[obj1, 'abc'],
[obj2, 'cba'],
[1, '2']
])
console.log(map1) //Map(3) { { name: 'why' } => 'abc', { age: 18 } => 'cba', 1 => '2' }
Map 的常见方法
Map 常见的属性:
- size:返回 Map 中元素的个数;
Map 常见的方法:
- set(key, value):在 Map 中添加 key、value,并且返回整个 Map 对象;
- get(key):根据 key 获取 Map 中的 value;
- has(key):判断是否包括某一个 key,返回 Boolean 类型;
- delete(key):根据 key 删除一个键值对,返回 Boolean 类型;
- clear():清空所有的元素;
- forEach(callback, [, thisArg]):通过 forEach 遍历 Map;
- Map 也可以通过 for of 进行遍历。
map1.forEach((item) => {
console.log(item)
})
/**
* abc
cba
2
*/
for (const item of map1) {
console.log(item)
}
/**
*
[ { name: 'why' }, 'abc' ]
[ { age: 18 }, 'cba' ]
[ 1, '2' ]
*/
WeakMap 的使用
和 Map 类型相似的另外一个数据结构称之为 WeakMap,也是以键值对的形式存在的。
那么和 Map 有什么区别呢?
- 区别一:WeakMap 的 key 只能使用对象,不接受其他的类型作为 key;
- 区别二:WeakMap 的 key 对对象想的引用是弱引用,如果没有其他引用引用这个对象,那么 GC 可以回收该对象;
//区别1
weakMap.set(1, 'abc') //TypeError: Invalid value used as weak map key
weakMap.set('aaa', 'abc') //TypeError: Invalid value used as weak map key
WeakMap 常见方法
WeakMap 常见的方法有四个:
- set(key, value):在 Map 中添加 key、value,并且返回整个 Map 对象;
- get(key):根据 key 获取 Map 中的 value;
- has(key):判断是否包括某一个 key,返回 Boolean 类型;
- delete(key):根据 key 删除一个键值对,返回 Boolean 类型;
WeakMap 应用场景
注意:WeakMap 也是不能遍历的
- 因为没有 forEach 方法,也不支持通过 for of 的方式进行遍历;
那么我们的 WeakMap 有什么作用呢?
应用场景 Vue3 的响应式原理
为什么要用 WeakMap?
如果对象不再用的话,可以直接销毁掉。如果发现对象已经销毁掉,那么这个 WeakMap 也就不会存在了。