搞懂内存泄漏到底是什么,造成内存泄漏的常见原因以及对应的解决方法

目录

1.内存泄漏到底是什么

2.造成内存泄漏的常见原因/情况有哪些,相应的解决方法

1.闭包引起的内存泄漏

2.未销毁事件监听器

3.忘记清除的定时器或者回调

4.循环引用

5.意外创建的全局变量(直接使用未声明的变量)


1.内存泄漏到底是什么

内存泄漏是指应用程序中的内存被错误地分配和释放,导致无法再次使用的内存堆积。这通常是由于开发者忘记释放不再使用的对象或数据而引起的。
内存泄漏会导致内存消耗过多,最终使应用程序性能下降,甚至崩溃。

2.造成内存泄漏的常见原因/情况有哪些,相应的解决方法

1.闭包引起的内存泄漏

闭包可以读取函数内部的变量,然后让这些变量始终保存在内存中。如果在使用结束后没有将局部变量清除,就可能导致内存泄露。

引申:
闭包的定义:闭包就是在一个函数A内部定义一个新的函数B,并且这个新函数B,调用了在函数A内定义的变量,并且在函数A外部被调用,这就形成了闭包

//闭包示例代码

function fn () {
  var a = "这是一个变量a";
  return function () {
    console.log(a);    //内部函数使用外部变量
  };
}

解决方法:
将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中。

//将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中

function fun(a) {
  console.log(a)
}
for (var i = 0; i < 10; i++) {
  fun(i)
}
fun = null
2.未销毁事件监听器

当你在DOM元素上添加事件监听器时,如果不手动删除它们,即使元素被销毁了,它们也将一直存在于内存中

// 为元素添加事件监听器

const button = document.getElementById('myButton');
button.addEventListener('click', () => {
  // 处理点击事件
});

解决方法:

在组件/元素卸载或不再需要时,手动删除事件监听器。

// 在组件/元素卸载或不再需要时,手动删除事件监听器

const button = document.getElementById('myButton');
const handleClick = () => {
  // 处理点击事件
};
button.addEventListener('click', handleClick);

// 移除事件监听器
button.removeEventListener('click', handleClick);

3.忘记清除的定时器或者回调

定时器中有 dom 的引用,即使 dom 删除了,但是定时器还在,所以内存中还是有这个 dom 

var serverData = loadData()
let timer = setInterval(function () {    //定时器timer
  var renderer = document.getElementById('renderer')
  if (renderer) {
    renderer.innerHTML = JSON.stringify(serverData)
  }
}, 5000)

// 观察者模式
var button = document.getElementById('myButton')
function onClick(element) {
  element.innerHTMl = "这是一个插入内容"
}
btn.addEventListener('click', onClick)

解决方法:

手动删除定时器和 dom。

clearInterval(timer);
4.循环引用

当两个或多个对象相互引用时,并且没有任何引用指向它们之中的任何一个时,它们将无法被垃圾回收

// 循环引用

function createObjects() {
  const obj1 = {};
  const obj2 = {};
  obj1.ref = obj2;
  obj2.ref = obj1;
}
createObjects();

解决方法:

避免循环引用,或者当不再需要这些引用时手动解除它们。

// 手动解除

function createObjects() {
  const obj1 = {};
  const obj2 = {};
  obj1.ref = obj2;
  obj2.ref = obj1;
  // 不再需要 obj1 和 obj2 的引用时,将它们设为 null
  obj1.ref = null;
  obj2.ref = null;
}
createObjects();

5.意外创建的全局变量(直接使用未声明的变量)

由于 js 对未声明变量的处理方式是在全局对象上创建该变量的引用,它在窗口关闭或重新刷新页面之前都不会被释放,如果未声明的变量缓存大量的数据,就会导致内存泄露

// a并未声明但直接使用(JS在非严格模式下)

function fn() {
  a = 'a是一个全局变量'
}
fn()



//或使用this定义的变量,在浏览器中,全局对象就是 window 对象

// function fn() {
//   this.a = 'a是一个全局变量'
// }
// fn()

解决方法:

尽量在定义变量之后再使用,或者使用JS严格模式(在 JavaScript 文件头部或者函数的顶部加上 use strict)。

(欢迎补充!!!!)



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值