1、什么是内存泄漏?
在程序中,由于疏忽或者错误,造成程序内存被占用而一直没有被释放从而失去控制,从而造成内存的浪费
2、垃圾回收机制
我的理解:在javascript中是有负责自动管理内存的机制的东西,我们称这种管理叫做垃圾回收机制管理,而且垃圾回收机制管理是自动进行的,是不可见的,我们平时所创建的基本类型、对象、函数...所有这些都需要内存,而这些内存的自动化管理和释放都需要 垃圾回收来管理。
所以垃圾回收机制它会管理哪些条件的内存呢?总的来就是那些 不可访问 的对象,进行回收释放;说不可访问,我们可以去理解以下可以访问的对象具有的特点就是:可达,比如:
1、一些基本的固有值,显而易见的
全局变量、函数内部变量和参数、调用其他函数的变量或参数,这些都是可达的,js引擎不会自动释放这些内存;
2、相互引用的对象之间,比如:
局部对象引用其他对象,那么该对象和其引用对象都是可达的。
3、垃圾回收机制常见策略
1、标记清除:比较常用的策略,它是指:在变量标记为“离开环境”时,被清除释放,当变量进入环境时标记为“进入环境”,在标记为“进入环境”时,不能释放内存,因为随时都有可能用到。例如:
var m = 0,n = 19 // 把 m,n,add() 标记为进入环境。
add(m, n) // 把 a, b, c标记为进入环境。
console.log(n) // a,b,c标记为离开环境,等待垃圾回收。
function add(a, b) {
a++
var c = a + b
return c
}
上述代码中,调用函数add,里面局部变量c,参数a,b在标记为进入环境时,不能释放,console.log(n)执行后,a,b,c 标记为离开环境,可以回收,但m,n变量不可以释放;
2、引用计数:在js引擎中有一张引用表,保存所有资源的引用次数,如果引用次数是0,表示该值不再引用,则可以释放内存,如果引用次数不为0,那么垃圾回收机制不会释放内存,从而导致内存泄漏,比如:
const arr = [1, 2, 3, 4];
console.log('hello world');
代码中数组[1,2,3,4]是一个值,会占用内存,变量 arr是引用了这个值,因此引用次数为1,尽管后面没有再用到,它仍然可以通过arr找到值,会持续占用内存,也遵循可达性,将会持续占用内存,如果想要回收,则 arr=null,就可以释放;
综上所述,垃圾回收机制虽然会自动释放一些内存空间,但并不代表内存不会泄漏,所以有些变量不再用到,需要检查是否存在对不再用到变量的引用,如果存在,需要手动释放;
常见内存泄漏情况
1、意外使用全局变量,比如函数内部使用全局变量:
function foo(arg) {
bar = "this is a hidden global variable";
}
或者:
function foo2(){
this.varable = "hello"
}
foo2();//调用后,this指向window全局变量
2、定时器,定时器不清除,一直占用内存,得不到释放,或者在定时器内调用外部函数,得不到释放;
3、闭包,内部函数引用外部函数变量,得不到释放,比如:
function bindEvent() {
var obj = document.createElement('XXX');
var unused = function () {
console.log(obj, '闭包内引用obj obj不会被释放');
};
obj = null; // 解决方法
}
4、不清理dom元素的引用,比如:
const refA = document.getElementById('refA');
document.body.removeChild(refA); // dom删除了
console.log(refA, 'refA'); // 但是还存在引用能console出整个div 没有被回收
refA = null;
console.log(refA, 'refA'); // 解除引用
5、监听事件的解除,监听的时候addEventListener,在不监听的时候要使用remveEventListener;