-
Notifications
You must be signed in to change notification settings - Fork 3
JS 中的垃圾回收机制和内存泄漏 #72
Description
JS 中的垃圾回收机制和内存泄漏
🌈 内存泄漏定义:操作系统在运行程序时需要不断为变量动态分配内存,在JavaScript中, 变量的内存空间的申请和释放都由程序自己处理(JS的垃圾回收机制),若程序没有正确回收和释放无用的内存,就会导致内存泄漏。
🌈 JS垃圾回收机制:找出不再使用的变量,然后释放掉其占用的内存,但是这个过程不是实时的,因为其开销比较大,所以垃圾回收器会按照固定的时间间隔周期性的执行。
依据无用内存检测方式的不同,可将垃圾回收机制有两种:
- 标记清除 (JS采用的方式)
- 引用计数
🌈 标记清除:当变量进入执行环境是,就标记这个变量为“进入环境”,当变量离开环境时,则将其标记为“离开环境”。垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间。
注意:标记=“变量是否在环境内”,而不是“变量是否被使用”,从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到他们。
🌈 引用计数:维护一张“引用表”,表内保存内存里面所有的资源的引用次数。如果一个值的引用次数是0,就表示这个值不再用到了,因此可以将这块内存释放。
引用计数最大的问题:循环引用。
解决循环引用的方法:在不使用对象的时候手工将它们设为空。
🌈 可能引发内存泄漏的几种情况:
- 意外的全局变量
- 遗忘的计时器或回调函数
- 闭包:已执行完毕的函数内局部变量仍被外部引用,因此仍被保留在内存中。
- 没有清理的DOM引用:当你用字典等形式保存了DOM节点内部数据结构时,DOM节点就存在两处引用(DOM树&字典),在删除时,需要同时删除DOM节点和其在表中的引用。
🌈 垃圾回收机制优化方案:尽量复用引用类型
以数组为例,用 arr.length=0 代替 arr=[] 清空数组,arr=[] 会重新创建一个空数组,原数组会变为内存垃圾。
对于无用的对象而言,可以通过手动设置 obj=null,让其尽快被垃圾回收机制回收。