js 内存泄露与垃圾回收

2023-03-11  本文已影响0人  欢西西西

不再使用的对象无法被垃圾回收机制回收,就是内存泄露(因为指针没有被置为null,就会导致无法释放掉它指向的内存)

一、常见内存泄露的情况

  1. 函数内部意外的全局变量
function add() {
    num = 10;
}
  1. 闭包(利用闭包特性去实现保存变量的情况并不算是内存泄露)
  1. 未被清空的定时器
  1. 未被解绑的事件监听

在Vue中,我们可以使用一个全局vue对象作为eventBus,组件中通过$on监听了某个事件,那么事件处理函数会保存在这个全局vue对象里;如果组件被销毁时未解绑事件,那么第二次创建该组件时,会出现重复绑定的情况,因为之前存的事件处理函数并未被销毁

  1. 对不再使用的DOM的引用

如果dom已经从文档中被删除,但js中依然存在对这个dom的引用,那么它也不会被垃圾回收,同时这个dom上注册的事件监听也不会被回收。如果这个节点不再需要,则引用应置为null

image.png image.png
  1. 打开控制台的console.log()语句

Vue项目中最容易出现内存泄漏的情况如下:

  1. 监听在window/document的事件未解绑,而组件已销毁
  2. EventBus的事件没有解绑,而组件已销毁
  3. Vuex的$store watch了之后没有unwatch
  4. 模块形成的闭包,使用完之后没有置为null
  5. 组件中创建的某对象引用了dom,但dom被清除时(例如使用v-if)没有销毁对象

二、定义内存不再使用的标准

1. 引用计数

跟踪记录每个值被引用的次数(多1次引用加1,少1次引用减1),如果这个次数是0了,就可以清除;
但有一个致命问题:循环引用。如果2个对象互相引用,但又无法再访问到这2个对象的时候,就无法清除了,导致内存泄露(访问不到,也不会被清除)

image.png

2. 标记清除法 mark and sweep

遍历所有可访问的对象、回收已不可访问的对象。
将不再使用的对象定义为无法到达的对象,从根部对象开始检测,能到达的对象都是要使用的对象,不能到达的,标记为可以清除的

image.png
上一篇 下一篇

猜你喜欢

热点阅读