目录
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)。
(欢迎补充!!!!)