是什么
一块内存不在被应用程序所使用时,由于某些原因这块内存没有返还给操作系统或者空闲内存池的现象。
会导致什么
运行缓慢,崩溃,高延迟,甚至一些与其他应用相关的问题。
常见的内存泄漏
1、意外的全局变量
// 在函数作用域中使用未声明的变量,该变量就是全局变量。
function foo(arg) {
// 变量bar相当于window.bar
bar = "this is a hidden global variable";
}
温馨提示:若使用全局变量来存储大量的数据,情确保使用过后将其置为null或者重新赋值;
因为,只有值未null或者重新赋值时才会被回收
2、被遗漏的定时器和回调函数
若定时器的周期函数还在运行,那么处理函数式不会被回收的,只有周期函数停止运行之后开始回收内存。
若周期函数没有被回收那么他的依赖数据也没有被回收。
温馨提示:及时清理定时器clearTimeout、clearInterval;
3、DOM之外的引用
把DOM节点保存在数据结构中,那么程序中会保留两个节点引用:一个在原本的DOM树中,另一个在数据结构中。
若该元素不需要时,要将两个地方的应用全部都清除掉。否则内存中会存有一份引用,不能被GC回收。
let eleObj = {
button: document.querySelector('#button'),
usersImg: []
};
// 若按钮不在被需要时
if (true) {
document.body.removeChild(document.getElementById('#button'));
delete eleObj.button
}
4、闭包
闭包是可以访问其他函数私有变量的函数,是内部函数和外部函数的桥梁。
const parentFn = () => {
let num = 666;
let subFn = () => {
console.log(num++)
};
return subFn;
};
let runFn = parentFn();
runFn();// 666
runFn();// 667
runFn();// 668
...
三次输出的结果不一样,原因:
如果两个对象互相引用,而不会被第三者引用,那么会被JavaScript回收。若有第三个对象引用,则不会被回收。
subFn被parentFn引用,parentFn被两者之外的runFn引用,因此parentFn执行后不会被回收。
使用闭包注意事项
1、由于闭包会把函数中的变量都保存在内存中,一次内存消耗是很大的,直接影响到页面性能;
2、闭包会在父函数外部,改变函数内部变量的值。所以,可以把父函数当做对象,闭包作为公用
属性,内部变量作为私有属性。切记,不要随便改变父函数内部变量的值。