JavaScript常见的内存问题主要有三种:
- 内存泄漏
- 内存膨胀
- 频繁垃圾回收
1、内存泄漏
原因
(1)什么是内存泄漏?
当进程不需要的内存,没有被垃圾清理回收机制清理回收,会出现内存泄漏的情况。
(2)JavaScript什么情况会导致内存泄漏?
当不需要使用的内存数据,依然被其他对象引用时,就会导致内存泄漏,因为被引用的数据无法被清理。
常见的场景
(1)闭包
闭包会引用父级函数的作用域中定义的变量,该变量会一直存在于内存中,直到没有进程中该变量被引用的数据被清理,闭包产生的内存数据才会被清理,引用闭包中的变量时,应该将引用数据最小化,已达到减少内存占用的情况。
(2)引用DOM
JavaScript引用了DOM节点对象,但是当DOM节点被移除后,JavaScript引用关系没有手动解除,那么该引用就会一直存在于内存中,而不能被回收。
(3)全局变量
window对象是常驻内存的,如果将对象绑定到window对象中,则该对象则会一直保存在内存中,及时该对象可能不再需要用到。
解决方案
在编写可能存在内存泄漏的代码时,需要注意对象的作用域,谨慎处理对象的引用,当不再需要引用的对象时,及时解除引用。
2、内存膨胀
原因
(1)什么是内存膨胀?
内存膨胀指的是大量数据长期占用内存,使内存长期处于高占用的状态。
(2)为什么会内存膨胀?
JavaScript中使用了大量数据的变量,且一直处于使用中的状态,这些数据通常是冗余不是立即需要使用的数据,或者想利用空间换取速度时,加载了过多不必要的数据的场景下,大概率可能会出现内存膨胀情况。
解决方案
合理管理数据,不过多加载暂时不需要的数据,根据需要利用缓存等手段,合理管理数据。
3、频繁垃圾回收
原因
(1)垃圾回收是什么?
垃圾是程序存放在内存空间的堆和栈中但不再被使用的数据。
JavaScript是一门自动垃圾回收的语言,JavaScript引擎的垃圾回收器会自动对JavaScript产生的垃圾进行回收。
(2)垃圾回收的时机是什么?
垃圾回收任务会在主线程中穿插执行,当垃圾存放空间快满时就会触发垃圾回收任务。
(3)为什么会频繁垃圾回收?
频繁生成临时变量,即快速地产生了可以被回收的垃圾,则会导致频繁出发垃圾回收机制。进行垃圾回收时,主线程任务会处于暂停状态,从而会导致页面卡顿的情况出现。
解决方案
尽量避免产生过多临时变量,可以尝试优化变量数量,比如采用复用变量等方式。