JS内存走漏
当我们用JS代码建立一个援用范例的时刻(以下简称对象),JS引擎会在内存中拓荒一块空间来寄存数据,并把指针援用交给谁人变量。内存是有限的,JS引擎必需保证当拓荒的对象没用的时刻,把所分派的内存空间开释出来,这个历程叫做渣滓接纳,担任接纳的叫做渣滓接纳器。
内存走漏是指我们已没法再经由过程JS代码来援用到某个对象,但渣滓接纳器却以为这个对象还在被援用,因而在接纳的时刻不会开释它。致使了分派的这块内存永久也没法被开释出来。假如如许的状况越来越多,会致使内存不够用而体系崩溃。
以下几种状况会致使内存走漏
绑定事宜没有移除
当页面中元素被移除或替代时,若元素绑定的事宜仍没被移除,在IE中不会作出适当处置惩罚,此时要先手工移除事宜,不然会存在内存走漏。
下面这类状况,我们移除input
元素以后,但其绑定的事宜仍在,渣滓接纳器会以为这个对象照样有效的,因而不会接纳这个对象,如许就致使当初为这个对象分派的内存没法被开释。
<div id="myDiv">
<input type="button" value="Click me" id="myBtn">
</div>
<script type="text/javascript">
var btn = document.getElementById("myBtn");
btn.onclick = function(){
document.getElementById("myDiv").innerHTML = "Processing...";
}
</script>
为了防止这类状况的发作,我们能够如许写
<div id="myDiv">
<input type="button" value="Click me" id="myBtn">
</div>
<script type="text/javascript">
var btn = document.getElementById("myBtn");
btn.onclick = function(){
// 手动将 btn.onclick 指向 null, 如许在删除 input 对象时,就不会发作内存走漏
btn.onclick = null;
document.getElementById("myDiv").innerHTML = "Processing...";
}
</script>
innerHTML将对象置为空
用innerHTML将对象置为空时,假如个中的元素被其他援用,也会发作内存走漏。
只管我们将div
的innerHTML
赋值为空,但由于援用p
指向div
中的p
元素,这时候渣滓接纳器会以为p
是有效的,由于被援用着,所以不会接纳p
占用的内存,致使内存走漏。
<div id='myDiv'>
<p id='myP'>innerHTML<p>
</div>
<script type="text/javascript">
var div = document.getElementById("myDiv");
var p = document.getElementById("myP");
div.innerHTML = '';
</script>
闭包
闭包的重要作用之一就是坚持状况
一般状况下,一个函数运转完毕,其内部的变量就应当被开释。但下面的状况是,函数outer
返回一个匿名函数,这个函数援用变量obj
。如许致使函数outer
运转完毕后,它的变量obj
并没有被开释。
function outer(){
var obj = {name:'xiaoxiong'};
return function(){
console.log(obj);
}
}
不测的全局变量
你能够经由过程加上
'use strict'
启用严厉形式来防止这类题目, 严厉形式会阻挠你建立不测的全局变量
函数运转完毕,变量依然存在,致使走漏。
function work() {
bar = "this is a hidden global variable";
}
// 上面的函数等价于
function work(arg) {
window.bar = "this is an explicit global variable";
}
如今我们总结一下,致使内存走漏的缘由大抵能够分为两种
- 函数运转完毕,其内部的变量仍存在
- 我们删除元素,但元素在内存中依然存在
致使这两种状况的根本缘由就是有其他变量援用这些元素。让渣滓接纳器以为这个元素照样有效的,因而想防止内存走漏,我们应当, 要删除一个元素,就要保证在删除这个元素之前,这个元素不被其他其他元素援用(将援用这个元素的指针指向其他元素或置空)