内存泄漏
# 前端内存泄漏
系统进程不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak)。当内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。Chrome 限制了浏览器所能使用的内存极限64位为 1.4GB,32 位为 1.0GB
# 引起内存泄漏的原因
# 意外的全局变量
由于 js 对未声明变量的处理方式是在全局对象上创建该变量的引用。如果在浏览器中,全局对象就是 window 对象。变量在窗口关闭或重新刷新页面之前都不会被释放,如果未声明的变量缓存大量的数据,就会导致内存泄露。
1.1 未声明变量
function fn() {
a = 'hello'
}
fn()
2
3
4
1.2 使用 this 创建的变量(this 的指向是 window)
function fn() {
this.a = 'hello'
}
fn()
2
3
4
解决方法:
避免创建全局变量 使用严格模式,在 JavaScript 文件头部或者函数的顶部加上 use strict
# 闭包引起的内存泄漏
于闭包可以读取函数内部的变量,然后让这些变量始终保存在内存中。如果在使用结束后没有将局部变量清除,就可能导致内存泄露。 所以避免乱用闭包
# 没有清理的DOM元素引用
在某个地方删除了元素,但是对象中还存在对dom的引用
// 在对象中引用DOM
var elements = {
btn: document.getElementById('btn'),
}
function doSomeThing() {
elements.btn.click()
}
function removeBtn() {
// 将body中的btn移除, 也就是移除 DOM树中的btn
document.body.removeChild(document.getElementById('btn'))
// 但是此时全局变量elements还是保留了对btn的引用, btn还是存在于内存中,不能被回收
}
2
3
4
5
6
7
8
9
10
11
12
13
解决方法:手动删除,elements.btn = null
# 被遗忘的定时器或者回调
定时器中有 dom 的引用,即使 dom 删除了,但是定时器还在,所以内存中还是有这个 dom。
解决方法:
手动删除定时器和 dom removeEventListener 移除事件监听
# 控制台日志,console.log
console.log打印的对象不能被垃圾回收,可能会导致内存泄露
# Map、Set对象
使用 Map 或 Set 存储对象时,同 Object 一致都是强引用,如果不将其主动清除引用,其同样会造成内存不自动进行回收。 如果使用 Map ,对于键为对象的情况,可以采用 WeakMap,WeakMap 对象同样用来保存键值对,对于键是弱引用(注:WeakMap 只对于键是弱引用),且必须为一个对象,而值可以是任意的对象或者原始值,由于是对于对象的弱引用,不会干扰 Js 的垃圾回收。
JS 的垃圾回收机制是如果我们持有对一个对象的引用,那么这个对象就不会被垃圾回收,这里的引用,指的就是 强引用 ,而弱引用就是一个对象若只被弱引用所引用,则被认为是不可访问(或弱可访问)的,因此可能在任何时刻被回收。
# 监听者模式
<template>
<div></div>
</template>
<script>
export default {
created() {
eventBus.on("test", this.doSomething)
},
beforeDestroy(){
eventBus.off("test", this.doSomething)
},
methods: {
doSomething() {
// do something
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在 beforeDestroy 组件销毁生命周期里将其清除即可。
# 内存三大件
前端关于内存方面主要有三个问题:
- 内存泄漏:对象已经不再使用但没有被回收,内存没有被释放,即内存泄漏,那想要避免就避免让无用数据还存在引用关系,也就是多注意上面说的常见的几种内存泄漏的情况。
- 内存膨胀:即在短时间内内存占用极速上升到达一个峰值,想要避免需要使用技术手段减少对内存的占用。
- 频繁 GC:同这个名字,就是 GC 执行的特别频繁,一般出现在频繁使用大的临时变量导致新生代空间被装满的速度极快,而每次新生代装满时就会触发 GC,频繁 GC 同样会导致页面卡顿,想要避免的话就不要搞太多的临时变量,因为临时变量不用了就会被回收,这和内存泄漏中说避免使用全局变量冲突,其实,只要把握好其中的度,不太过分就 OK。
# 排查内存泄漏
https://juejin.cn/post/6984188410659340324#heading-9
- 01
- 2023/07/03 00:00:00
- 02
- 2023/04/22 00:00:00
- 03
- 2023/02/16 00:00:00