1、什么是内存泄露
内存泄露是对于开发来讲不再使用的内容,但是垃圾回收器无法回收。
js主要采用引用计数法来标记一块内存是不是垃圾。当这块内存无引用的时候,就是垃圾内存。
2、闭包一定会造成了内存泄露吗?
内存泄露和闭包没有必然关系,错误的使用才会导致内存的泄露,闭包只是可能会加剧这种使用错误。
3、什么情况闭包会造成内存泄露
3.1.当本应销毁的函数没有销毁,导致其关联的词法环境无法销毁,造成内存泄漏
increase函数中引用了所在词法环境中的doms变量,所用doms在increase不销毁的情况,doms也不会被销毁。
button.addEventListener('click', increase);调用increase函数,因为绑定了是click事件,浏览器也不知道,你这个按钮到底要点击几次,所以浏览器不会销毁increase函数。
function createIncrease() {
const doms=new Array(100000).fill(0).map(i=>{
const dom = document.createElement('div');
dom.innerHTML=i;
return dom;
});
function increase(){
doms.forEach(dom=>{
dom.innerHTML=Number(dom.innerHMLT)+1;
})
};
return increase;
}
const increase=createIncrease();
let button = document.getElementById('someButton');
button.addEventListener('click', increase);
改造内存泄露
/**改造前**/
const increase=createIncrease();
let button = document.getElementById('someButton');
button.addEventListener('click', increase);
/**改造后**/
button.addEventListener('click', createIncrease(),{once: true});
3.2.当多个函数共享词法环境时,可能导致词法环境膨胀,从而可能导致出现无法触达但也无法回收的内存空间
函数increase并没有引用doms变量,temp引用了doms变量,temp虽然没有使用,会被销毁掉,因为increase和temp所在同一块词法环境,所以浏览器就没有这块词法环境变量中的doms进行回收,从而造成了doms无法访问,也无法回收
function createIncrease() {
const doms=new Array(100000).fill(0).map(i=>{
const dom = document.createElement('div');
dom.innerHTML=i;
return dom;
});
function increase(){
};
function temp(){
doms.forEach(dom=>{
dom.innerHTML=Number(dom.innerHMLT)+1;
})
}
return increase;
}
const increase=createIncrease();
let button = document.getElementById('someButton');
button.addEventListener('click', increase);