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 有一个非常常用的功能就是给数组去重。

  1. const set1 = new Set()
  2. set1.add(10)
  3. set1.add(20)
  4. set1.add(30)
  5. set1.add(40)
  6. set1.add(40)
  7. //元素不会重复
  8. console.log(set1) //Set(4) { 10, 20, 30, 40 }

但是如果是对象的话

  1. set1.add({})
  2. set1.add({})
  3. console.log(set1) //Set(6) { 10, 20, 30, 40, {}, {} }

但是我们写为如下形式

  1. //但是如果我们写为这个形式,就只会出现一次啦
  2. const obj = { 1: '1' }
  3. set1.add(obj)
  4. set1.add(obj)
  5. console.log(set1) //Set(7) { 10, 20, 30, 40, {}, {}, { '1': '1' } }

Set 中存放的元素是不会重复的。那么 Set 有一常用的功能就是给数组去重

  1. const arr = [10, 20, 30, 40, 30, 20]
  2. const arrSet = new Set(arr)
  3. console.log(arrSet) //Set(4) { 10, 20, 30, 40 }
  4. const newArr = [...arrSet]
  5. console.log(newArr) //[ 10, 20, 30, 40 ]

set 常见方法

Set 常见的属性:

  • size:返回 Set 中元素的个数;

Set 常用的方法:

  1. add(value):添加某个元素,返回 Set 对象本身;
  2. delete(value):从 set 中删除和这个值相等的元素,返回 boolean 类型;
  3. has(value):判断 set 中是否存在某个元素,返回 boolean 类型;
  4. clear():清空 set 中所有的元素,没有返回值;
  5. forEach(callback, [, thisArg]):通过 forEach 遍历 set;

另外 Set 是支持 for of 的遍历的。

  1. for (const item of set1) {
  2. console.log(item)
  3. }

WeakSet 使用

和 Set 类似的另外一个数据结构称之为 WeakSet,也是内部元素不能重复的数据结构。

那么和 Set 有什么区别呢?

  1. 区别一:WeakSet 中只能存放对象类型,不能存放基本数据类型;
  2. 区别二:WeakSet 对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么 GC 可以对该对象进行回收;
  1. const wset = new WeakSet()
  2. //区别1:不能存放基本数据类型
  3. wset.add(10) //TypeError: Invalid value used in weak set
  4. console.log(wset)
  5. let obj = {
  6. name: 'why'
  7. }
  8. //建立的是弱引用
  9. wset.add(obj)
  10. console.log(wset) //WeakSet { <items unknown> }

WeakSet 应用场景

注意:WeakSet 不能遍历

  • 因为 WeakSet 只是对对象的弱引用,如果我们遍历获取到其中的元素,那么有可能造成对象不能正常的销毁。
  • 所以存储到 WeakSet 中的对象是没办法获取的;

那么这个东西有什么用呢?

  • 事实上这个问题并不好回答,我们来使用一个 Stack Overflow 上的答案;

14_set:map等 - 图1

Map

Map 的基本使用

另外一个新增的数据结构是 Map,用于存储映射关系。

  • 但是我们可能会想,在之前我们可以使用对象来存储映射关系,他们有什么区别呢?
  • 事实上我们对象存储映射关系只能用字符串(ES6 新增了 Symbol)作为属性名(key);
  1. const obj1 = { name: 'why' }
  2. const obj2 = { age: 18 }
  3. const info = {
  4. [obj1]: 'aaa',
  5. [obj2]: 'bbb'
  6. }
  7. console.log(info) //{ '[object Object]': 'bbb' }

对象类型会转换为[object Object],因此就只能是这一个。

  • 某些情况下我们可能希望通过其他类型作为 key,比如对象,这个时候会自动将对象转成字符串来作为 key;

那么我们就可以使用 Map:

  1. const obj1 = { name: 'why' }
  2. const obj2 = { age: 18 }
  3. const map = new Map()
  4. map.set(obj1, 'abc')
  5. map.set(obj2, 'cba')
  6. console.log(map) //Map(2) { { name: 'why' } => 'abc', { age: 18 } => 'cba' }

创建 Map 的方式

  1. const map1 = new Map([
  2. [obj1, 'abc'],
  3. [obj2, 'cba'],
  4. [1, '2']
  5. ])
  6. 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 进行遍历。
  1. map1.forEach((item) => {
  2. console.log(item)
  3. })
  4. /**
  5. * abc
  6. cba
  7. 2
  8. */
  9. for (const item of map1) {
  10. console.log(item)
  11. }
  12. /**
  13. *
  14. [ { name: 'why' }, 'abc' ]
  15. [ { age: 18 }, 'cba' ]
  16. [ 1, '2' ]
  17. */

WeakMap 的使用

和 Map 类型相似的另外一个数据结构称之为 WeakMap,也是以键值对的形式存在的。

那么和 Map 有什么区别呢?

  1. 区别一:WeakMap 的 key 只能使用对象,不接受其他的类型作为 key;
  2. 区别二:WeakMap 的 key 对对象想的引用是弱引用,如果没有其他引用引用这个对象,那么 GC 可以回收该对象;
  1. //区别1
  2. weakMap.set(1, 'abc') //TypeError: Invalid value used as weak map key
  3. weakMap.set('aaa', 'abc') //TypeError: Invalid value used as weak map key

WeakMap 常见方法

WeakMap 常见的方法有四个:

  1. set(key, value):在 Map 中添加 key、value,并且返回整个 Map 对象;
  2. get(key):根据 key 获取 Map 中的 value;
  3. has(key):判断是否包括某一个 key,返回 Boolean 类型;
  4. delete(key):根据 key 删除一个键值对,返回 Boolean 类型;

WeakMap 应用场景

注意:WeakMap 也是不能遍历的

  • 因为没有 forEach 方法,也不支持通过 for of 的方式进行遍历;

那么我们的 WeakMap 有什么作用呢?

应用场景 Vue3 的响应式原理

14_set:map等 - 图2

为什么要用 WeakMap?

如果对象不再用的话,可以直接销毁掉。如果发现对象已经销毁掉,那么这个 WeakMap 也就不会存在了。