一文搞清楚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


目录
打赏
0
0
0
0
3
分享
相关文章
哈希表模拟封装unordered_map和unordered_set
哈希表模拟封装unordered_map和unordered_set
|
3月前
|
你对Collection中Set、List、Map理解?
你对Collection中Set、List、Map理解?
83 18
你对Collection中Set、List、Map理解?
只会“有序无序”?面试官嫌弃的List、Set、Map回答!
小米,一位热衷于技术分享的程序员,通过与朋友小林的对话,详细解析了Java面试中常见的List、Set、Map三者之间的区别,不仅涵盖了它们的基本特性,还深入探讨了各自的实现原理及应用场景,帮助面试者更好地准备相关问题。
78 20
【C++】map、set基本用法
本文介绍了C++ STL中的`map`和`set`两种关联容器。`map`用于存储键值对,每个键唯一;而`set`存储唯一元素,不包含值。两者均基于红黑树实现,支持高效的查找、插入和删除操作。文中详细列举了它们的构造方法、迭代器、容量检查、元素修改等常用接口,并简要对比了`map`与`set`的主要差异。此外,还介绍了允许重复元素的`multiset`和`multimap`。
75 3
【C++】map、set基本用法
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
41 5
es6加上symbol的基础数据类型
【10月更文挑战第30天】ES6 中的 `Symbol` 作为一种新的基础数据类型,为 JavaScript 提供了一种创建唯一标识符和处理对象属性名冲突的有效方式,丰富了 JavaScript 的数据类型体系和编程模式,在实际开发中具有重要的应用价值。
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
该文章详细介绍了ES6中Set和Map数据结构的特性和使用方法,并探讨了它们在前端开发中的具体应用,包括如何利用这些数据结构来解决常见的编程问题。
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
|
6月前
|
【数据结构】map&set详解
本文详细介绍了Java集合框架中的Set系列和Map系列集合。Set系列包括HashSet(哈希表实现,无序且元素唯一)、LinkedHashSet(保持插入顺序的HashSet)、TreeSet(红黑树实现,自动排序)。Map系列为双列集合,键值一一对应,键不可重复,值可重复。文章还介绍了HashMap、LinkedHashMap、TreeMap的具体实现与应用场景,并提供了面试题示例,如随机链表复制、宝石与石头、前K个高频单词等问题的解决方案。
67 6
【数据结构】map&set详解
Set、Map、WeakSet 和 WeakMap 的区别
在 JavaScript 中,Set 和 Map 用于存储唯一值和键值对,支持多种操作方法,如添加、删除和检查元素。WeakSet 和 WeakMap 则存储弱引用的对象,有助于防止内存泄漏,适合特定场景使用。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等