一文搞清楚ES6新增数据结构 Symbol Map WeakMap Set WeakSet(二)

简介: 一文搞清楚ES6新增数据结构 Symbol Map WeakMap Set WeakSet

WeakSet

WeakSet的基本使用


  • 和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构。
  • 那么和Set有什么区别呢?
  • 区别一:WeakSet中只能存放对象类型,不能存放基本数据类型;
  • 区别二:WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么垃圾回收机制可以对该对象进行回收;

代码演示

const weakSet = new WeakSet()
// 1.区别一: 只能存放对象类型
// TypeError: Invalid value used in weak set
// weakSet.add(10)
// 强引用和弱引用的概念(看图)
// 2.区别二: 对对象是一个弱引用
let obj = { 
  name: "why"
}
weakSet.add(obj)
const set = new Set()
// 建立的是强引用
set.add(obj)
// 建立的是弱引用
weakSet.add(obj)

WeakSet常见方法


  • add(value):添加某个元素,返回WeakSet对象本身;
  • delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型;
  • has(value):判断WeakSet中是否存在某个元素,返回boolean类型;

WeakSet的应用


  • 注意:WeakSet不能遍历
  • 因为WeakSet只是对对象的弱引用,如果我们遍历获取到其中的元素,那么有可能造成对象不能正常的销毁。
  • 所以存储到WeakSet中的对象是没办法获取的;
  • 那么这个东西有什么用呢?
  • 事实上这个问题并不好回答,我们来使用一个Stack Overflow上的答案;

代码演示

不能通过非构造方法创建出来的对象 调用构造函数的方法

const personSet = new WeakSet()
class Person {
  constructor() {
    personSet.add(this)
  }
  running() {
    if (!personSet.has(this)) {
      throw new Error("不能通过非构造方法创建出来的对象调用running方法")
    }
    console.log("running~", this)
  }
}
let p = new Person()
p.running()
p = null
p.running.call({name: "why"})

Map

Map的基本使用


  • 另外一个新增的数据结构是Map,用于存储映射关系。
  • 但是我们可能会想,在之前我们可以使用对象来存储映射关系,他们有什么区别呢?
  • 事实上我们对象存储映射关系只能用字符串(ES6新增了Symbol)作为属性名(key);
  • 某些情况下我们可能希望通过其他类型作为key,比如对象,这个时候会自动将对象转成字符串来作为key;
  • 那么我们就可以使用Map:

代码使用

// 1.JavaScript中对象中是不能使用对象来作为key的
const obj1 = { name: "why" }
const obj2 = { name: "kobe" }
const info = {
   [obj1]: "aaa",
   [obj2]: "bbb"
}
console.log(info)
// 2.Map就是允许我们对象类型来作为key的
// 构造方法的使用
const map = new Map()
map.set(obj1, "aaa")
map.set(obj2, "bbb")
map.set(1, "ccc")
console.log(map)
const map2 = new Map([[obj1, "aaa"], [obj2, "bbb"], [2, "ddd"]])
console.log(map2)
// Map(3) {{…} => 'aaa', {…} => 'bbb', 2 => 'ddd'}

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进行遍历。

代码演示

// 常见的属性和方法
console.log(map2.size)
// set
map2.set("why", "eee")
console.log(map2)
// get(key)
console.log(map2.get("why"))
// has(key)
console.log(map2.has("why"))
// delete(key)
map2.delete("why")
console.log(map2)
// clear
// map2.clear()
// console.log(map2)
// 遍历map
map2.forEach((item, key) => {
  console.log(item, key)
})
for (const item of map2) {
  console.log(item[0], item[1])
}
for (const [key, value] of map2) {
  console.log(key, value)
}

WeakMap

WeakMap的使用


  • 和Map类型的另外一个数据结构称之为WeakMap,也是以键值对的形式存在的。
  • 那么和Map有什么区别呢?
  • 区别一:WeakMap的key只能使用对象,不接受其他的类型作为key;
  • 区别二:WeakMap的key对对象想的引用是弱引用,如果没有其他引用引用这个对象,那么GC可以回收该对象;
  • WeakMap常见的方法有四个:
  • set(key, value):在Map中添加key、value,并且返回整个Map对象;
  • get(key):根据key获取Map中的value;
  • has(key):判断是否包括某一个key,返回Boolean类型;
  • delete(key):根据key删除一个键值对,返回Boolean类型;

代码演示

const obj = {name: "obj1"}
// 1.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 { <items unknown> }
console.log(weakMap)

WeakMap的应用


  • 注意:WeakMap也是不能遍历的
  • 因为没有forEach方法,也不支持通过for of的方式进行遍历;
  • 那么我们的WeakMap有什么作用呢?

代码演示

可以做对象的依赖收集

先把对象的属性和属性对应的依赖,存储为Map结构,一个key 对应一组收集的函数依赖

然后把对象 和Map 结构存储为weakMap

当代理的对象有变化时,我们去weakMap 取key,再执行依赖函数集

// 应用场景(vue3响应式原理)
const obj1 = {
  name: "why",
  age: 18
}
function obj1NameFn1() {
  console.log("obj1NameFn1被执行")
}
function obj1NameFn2() {
  console.log("obj1NameFn2被执行")
}
function obj1AgeFn1() {
  console.log("obj1AgeFn1")
}
function obj1AgeFn2() {
  console.log("obj1AgeFn2")
}
// 1.创建WeakMap
const weakMap = new WeakMap()
// 2.收集依赖结构
// 2.1.对obj1收集的数据结构
const obj1Map = new Map()
obj1Map.set("name", [obj1NameFn1, obj1NameFn2])
obj1Map.set("age", [obj1AgeFn1, obj1AgeFn2])
weakMap.set(obj1, obj1Map)
// 2.2如果obj1.name发生了改变
// Proxy/Object.defineProperty
obj1.name = "james"
const targetMap = weakMap.get(obj1)
const fns = targetMap.get("name")
fns.forEach(item => item())

5f7960c7d6df9745728a755b4491963.png


相关文章
|
19天前
|
存储 JavaScript 前端开发
Set、Map、WeakSet 和 WeakMap 的区别
在 JavaScript 中,Set 和 Map 用于存储唯一值和键值对,支持多种操作方法,如添加、删除和检查元素。WeakSet 和 WeakMap 则存储弱引用的对象,有助于防止内存泄漏,适合特定场景使用。
|
22天前
|
存储 缓存 Java
【用Java学习数据结构系列】HashMap与TreeMap的区别,以及Map与Set的关系
【用Java学习数据结构系列】HashMap与TreeMap的区别,以及Map与Set的关系
30 1
|
2月前
|
算法
你对Collection中Set、List、Map理解?
你对Collection中Set、List、Map理解?
32 5
|
14天前
|
存储
ES6中的Set数据结构的常用方法和使用场景
ES6中的Set数据结构的常用方法和使用场景
|
2月前
|
存储 JavaScript 前端开发
js的map和set |21
js的map和set |21
|
2月前
|
存储 前端开发 API
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
该文章详细介绍了ES6中Set和Map数据结构的特性和使用方法,并探讨了它们在前端开发中的具体应用,包括如何利用这些数据结构来解决常见的编程问题。
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
|
20天前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
18 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
1天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
20天前
初步认识栈和队列
初步认识栈和队列
48 10
|
14天前
数据结构(栈与列队)
数据结构(栈与列队)
15 1