JS內存泄露

JS內存泄露

當咱們用JS代碼建立一個引用類型的時候(如下簡稱對象),JS引擎會在內存中開闢一塊空間來存放數據,並把指針引用交給那個變量。內存是有限的,JS引擎必須保證當開闢的對象沒用的時候,把所分配的內存空間釋放出來,這個過程叫作垃圾回收,負責回收的叫作垃圾回收器。javascript

內存泄漏是指咱們已經沒法再經過JS代碼來引用到某個對象,但垃圾回收器卻認爲這個對象還在被引用,所以在回收的時候不會釋放它。致使了分配的這塊內存永遠也沒法被釋放出來。若是這樣的狀況愈來愈多,會致使內存不夠用而系統崩潰。java

如下幾種狀況會致使內存泄露閉包

綁定事件沒有移除

當頁面中元素被移除或替換時,若元素綁定的事件仍沒被移除,在IE中不會做出恰當處理,此時要先手工移除事件,否則會存在內存泄露。函數

下面這種狀況,咱們移除input元素以後,但其綁定的事件仍在,垃圾回收器會認爲這個對象仍是有用的,所以不會回收這個對象,這樣就致使當初爲這個對象分配的內存沒法被釋放。this

<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將對象置爲空時,若是其中的元素被其餘引用,也會發生內存泄漏。code

儘管咱們將divinnerHTML賦值爲空,但由於引用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並無被釋放。ip

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";
}

如今咱們總結一下,致使內存泄漏的緣由大體能夠分爲兩種

  • 函數運行結束,其內部的變量仍存在
  • 咱們刪除元素,但元素在內存中仍然存在

致使這兩種狀況的根本緣由就是有其餘變量引用這些元素。讓垃圾回收器認爲這個元素仍是有用的,所以想避免內存泄漏,咱們應該, 要刪除一個元素,就要保證在刪除這個元素以前,這個元素不被其餘其餘元素引用(將引用這個元素的指針指向其餘元素或置空)

相關文章
相關標籤/搜索