【ES6】带你探究ES6入门WeakSet和WeakMap和了解JS垃圾回收机制

前言

JavaScript是一种高级的、基于事件驱动的编程语言,它的垃圾回收机制是自动管理内存的关键组成部分。并且在ES6(ECMAScript 2015)中引入了WeakSetWeakMap这两个数据结构,它们为开发者提供了更灵活的内存管理方式,特别是在涉及到临时对象引用和垃圾回收方面。

今天,我们来潜聊一下JavaScript的垃圾回收机制和WeakSetWeakMap

在前文:【ES6干货】带你手把手学习js中的Set和Map!! - 掘金 (juejin.cn)已经为大家介绍了ES6+Set和Map的相关知识。大家感兴趣的话可以去学习一下!

垃圾回收机制

垃圾回收是一种自动管理内存的机制,通过检测不再被引用的对象,并将其释放,以防止内存泄漏。在JavaScript中,最常见的垃圾回收方式是基于引用计数和标记清除。引用计数是通过跟踪引用对象的次数来确定何时释放内存。标记清除则是通过标记不再需要的对象,然后清除它们。

不知道大家以前有没有接触过其他编程语言!在传统的编程语言当中,垃圾回收机制是不会自动执行的,需要我们程序员自己进行手动 分配和释放内存,这样容易导致内存泄漏和悬空指针等等人为的失误。所以在JavaScript中,为了避免这些问题,采取了一种自动垃圾回收的机制!

垃圾回收机制的工作原理:垃圾回收机制的主要目标是找到并释放不再被程序使用的内存。

  1. 引用计数: 这是一种简单的垃圾回收算法,它通过在内存中跟踪对象的引用次数来确定何时释放对象。当引用次数变为零时,说明对象不再被使用,可以安全地被回收。
  2. 标记清除: 这是一种更复杂但更普遍的垃圾回收算法。它从一组根对象开始,标记所有可以访问到的对象。然后,它清除未被标记的对象,因为它们不再可达。

在JavaScript中,垃圾回收机制主要依赖于标记清除算法,也就是我们上面所说的第二种方法,我们的JavaScript系统会自己周期性地执行垃圾回收操作,找到不再被引用的对象并释放它们占用的内存,也就意味着,这个周期性地执行并不受我们控制!而由编译系统自己决定!

我们通过这样一个案例来了解一下JavaScript中的垃圾回收机制

js 复制代码
// 例子:垃圾回收的示意
let obj1 = { name: '小美' };
let obj2 = { name: '张三' };

obj1 = null; // 此时obj1不再引用任何对象
// 在垃圾回收周期中,obj1引用的对象将被标记为可回收

也就是说!我们可以通过将一个对象Obj = nullObj不在引用任何对象,也就意味着:我们现在把Obj标记为可清理,可回收的状态,那么,下次垃圾回收机制再次运行的时候,则会自动地释放掉Obj的内存。

WeakSet: 弱引用的集合

接下来,我们来学习一下WeakSet

WeakSet是一种集合,其中的元素只能是对象和Symbol,并且这些对象是弱引用的。这意味着,如果一个对象只被WeakSet引用,而没有被其他强引用引用,那么这个对象将被垃圾回收。

WeakSet其实与Set比较类似,都是不重复的集合!

我们来看看这个案例:

js 复制代码
let weakset = new WeakSet();
var obj = new Object()
weakset.add(obj)//不报错
weakset.add(Symbol())//不报错
weakset.add(1)//报错

在这个案例当中,我们可以看到WeakSet()中只能存储对象和Symbol如果是其他数据类型都会报错!

WeakSet是弱引用?什么意思呢?意思就是:垃圾回收机制不会考虑WeakSet对该对象的引用,如果没有其他对象引用这个对象,垃圾回收机制就会一点面子不给WeakSet将它回收掉!

具体我们来看一个案例

js 复制代码
let obj = {name:'亚索'}
let ws = new WeakSet()//只能存symbol和对象
ws.add(obj)
//浏览器的垃圾机制是不受我们掌控的,我们不知道什么时候会把它回收掉,垃圾回收机制的执行机时间是不受我们掌控的
//如果,下面没有有效应用,obj就会被销毁
console.log(ws);//输出:WeakSet { <items unknown> }

同时,WeakSet中引用的对象,也会随着这个对象的销毁而销毁!也就是说,如果我们人为地去销毁那个对象的话!那么WeakSet中的这个对象也会不复存在!!我们来看看这个案例!

javascript 复制代码
let weakSet = new WeakSet();
let obj = {};

weakSet.add(obj);
console.log(weakSet.has(obj)); // true

// 当对象被销毁后,WeakSet 也会自动删除对应的引用
obj = null;
console.log(weakSet.has(obj)); // false

WeakSet常用于存储一组对象,而不需要担心这些对象是否还存在于其他地方。它对于缓存和临时数据存储非常有用。

WeakSet的方法

1. add(value):

add 方法用于在 WeakSet 中添加新的元素。

js 复制代码
let weakSet = new WeakSet();
let obj = {};
weakSet.add(obj);

2. has(value):

has 方法用于检查 WeakSet 中是否存在特定元素。

js 复制代码
console.log(weakSet.has(obj)); // true

3. delete(value):

delete 方法用于从 WeakSet 中删除特定元素。

js 复制代码
weakSet.delete(obj);
console.log(weakSet.has(obj)); // false

注意事项:

  • WeakSet 没有迭代方法,因此不能使用 forEachfor ...of进行遍历。
  • 由于元素是弱引用的,如果没有其他强引用指向元素,WeakSet 在垃圾回收时会自动清理不再被引用的元素。

WeakMap: 弱引用的键值对集合

WeakMap是一种键值对的集合,其中的键是弱引用的。与WeakSet类似,如果一个对象只被WeakMap引用,而没有被其他强引用引用,那么这个对象将被垃圾回收。

同时,WeakMap只能存储对象和Symbol,这一点其实与WeakSet相同!

js 复制代码
let weakmap = new WeakMap();
var obj = new Object()
weakmap.set(obj,12)//不报错
weakmap.add(Symbol(),45)//不报错
weakmap.add(1,1)//报错
weakmap.add(null,1)//报错

WeakMap的存储解构和Map相同!但是WeakMapkey值只能是对象和Symbol,否则就会报错!

同样的,WeakMap也是弱引用!垃圾回收机制不会考虑WeakMap对该对象的引用,如果没有其他对象引用这个对象,垃圾回收机制就会一点面子不给WeakMap将它回收掉!

在垃圾回收机制前面WeakMapWeakSet就是两个难兄难弟!

我们来看一个案例!

js 复制代码
let obj = {name:'锐雯'}
let wm = new WeakMap()
console.log(wm.set(obj,5));//输出:WeakMap { <items unknown> }

作为两个难兄难弟,WeakMapWeaSet一样一样的"卑微",WeakMap中引用的对象,也会随着这个对象的销毁而销毁!!

javascript 复制代码
let weakMap = new WeakMap();
let key = {};
let value = '你好';

weakMap.set(key, value);
console.log(weakMap.has(key)); // 输出:true
console.log(weakMap.get(key)); // 输出:'你好'
// 当键对象被销毁后,WeakMap 也会自动删除对应的键值对
key = null;
console.log(weakMap.has(key)); // 输出:false
console.log(weakMap.get(key)); // 输出:undefined

WeakMap通常用于将一些数据与特定对象关联,而无需担心这些数据会阻止对象被垃圾回收。它在处理私有数据和缓存方面非常有用。

WeakMap的方法

1. set(key, value):

  • set 方法用于向 WeakMap 中添加键值对。
js 复制代码
let weakMap = new WeakMap();
let key = {};
let value = 'Some value';

weakMap.set(key, value);

2. get(key):

  • get 方法用于获取指定键对应的值。
js 复制代码
console.log(weakMap.get(key)); // 'Some value'

3. has(key):

  • has 方法用于检查 WeakMap 中是否存在特定键。
js 复制代码
console.log(weakMap.has(key)); // true

4. delete(key):

  • delete 方法用于从 WeakMap 中删除指定键值对。
js 复制代码
weakMap.delete(key);
console.log(weakMap.has(key)); // false

注意事项:

  • WeakMap不支持迭代方法(如forEach),因为弱引用的键不允许直接遍历。
  • 由于键是弱引用的,如果没有其他强引用指向键,WeakMap 在垃圾回收时会自动清理不再被引用的键值对。
  • WeakMap 的方法相对较少,主要是因为其设计目的是提供一种不会阻止垃圾回收的弱引用集合。

WeakMap主要用于在需要与对象关联信息但又不希望干扰垃圾回收的情况下使用,例如存储对象的私有数据。弱引用的特性使得WeakMap在这些情况下更为合适。

总结

在JavaScript中,垃圾回收机制是确保应用程序高效运行的重要组成部分。垃圾回收机制通过自动管理内存,避免了手动内存管理的复杂性和错误,就像是一个自动扫地机器人一样,自动地为我们清理内存,这不仅提高了开发效率、降低了内存泄漏的风险,还能够增强我们写的代码的可维护性和健壮性。

同时呢:WeakSetWeakMap为开发者提供了更灵活的内存管理方式,特别是在处理临时数据、私有数据以及避免内存泄漏方面。

大家感兴趣的可以去深入学习和理解一下这WeakSetWeakMap的相关知识,这有有助于我们提高代码的性能和可维护性。

对于 WeakSetWeakMap,我们可以知道如下:

  • 避免内存泄漏: WeakSetWeakMap弱引用特性有助于防止因为对象被引用而无法被垃圾回收,从而减少内存泄漏的风险。

  • 临时数据存储: 这两种数据结构非常适合存储一些临时性的数据,因为它们会随着对象的销毁而自动清理。

  • 私有数据管理: WeakMap常被用于存储与对象关联的私有数据,因为这样的数据不会影响垃圾回收。

  • 不可迭代: 由于弱引用的特性,WeakSetWeakMap不可迭代,即不能通过循环获取其中的所有元素或键值对。

好啦!我们今天的学习就到这里为止啦!

大家有任何想法欢迎大家评论哦~

点个小赞鼓励支持一下吧!🌹🌹🌹

个人gitee库:MycodeSpace: 主要应用的仓库,记录学习coding中的点点滴滴 (gitee.com)

相关推荐
慧一居士5 分钟前
flex 布局完整功能介绍和示例演示
前端
DoraBigHead7 分钟前
小哆啦解题记——两数失踪事件
前端·算法·面试
一斤代码6 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子6 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年6 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子6 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina6 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路7 小时前
React--Fiber 架构
前端·react.js·架构
coderlin_7 小时前
BI布局拖拽 (1) 深入react-gird-layout源码
android·javascript·react.js
伍哥的传说7 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js