JavaScript 中常见的内存泄漏

JavaScript中常见的内存泄漏包含以下几种形式

  • 意外的全局变量
  • 未解除的监听事件
  • 未清除的定时器或者回调函数
  • 闭包或者循环引用
  • 单例对象或全局对象引用循环

意外的全局变量

在函数内未使用var, let, 或 const声明一个变量,它会被创建为一个全局变量,如果这个变量指向一个对象或数组,可能导致内存泄漏。

function func() {

  obj = {} // 这将会创建一个全局变量,除非显式地删除,否则不会被垃圾回收
  // something
  // obj = null 删除变量的引用
}

未解除的监听事件

给一个DOM元素或者全局事件添加了事件监听器,但在移除该元素之前没有移除监听器,导致该元素及其相关的函数无法被垃圾回收。

const el = document.getElementById('el');
el.addEventListener('click', function onClick() {
    // 处理点击事件
});

// 当元素或组件被移除时,应该移除事件监听器
// element.removeEventListener('click', onClick);

未清除的定时器或者回调函数

设置了setIntervalsetTimeout,但是在不需要它们时没有清除。

let timerId
function startTimer() {
    timerId = setInterval(function intervalCallback() {
        // 定时器逻辑
    }, 1000);
}
 
// 当不需要定时器时
// clearInterval(timerId);

闭包或者循环引用

函数内部创建了一个闭包,闭包内部引用了外部的变量,导致这些变量不能被垃圾回收。

function createLeak() {
    const leak = {};
 
    return function leakyClosure() {
        // leakyClosure内部会引用leak,除非leakyClosure不再被调用或显式解除对leak的引用
    }
}
 
const leakyFunction = createLeak();
// leakyClosure = null

单例对象或全局对象引用循环

对象间相互引用,导致它们不能被垃圾回收。

let objA = {};
let objB = {};
 
objA.reference = objB;
objB.reference = objA;
 
// 移除引用来打破引用循环
// delete objA.reference;
// delete objB.reference;

解决这些问题的方法通常是确保不再需要的变量被解除引用,例如将变量设置为null,或者在不需要时清除定时器、事件监听器等。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容