當咱們用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將對象置爲空時,若是其中的元素被其餘引用,也會發生內存泄漏。code
儘管咱們將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
並無被釋放。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"; }
如今咱們總結一下,致使內存泄漏的緣由大體能夠分爲兩種
致使這兩種狀況的根本緣由就是有其餘變量引用這些元素。讓垃圾回收器認爲這個元素仍是有用的,所以想避免內存泄漏,咱們應該, 要刪除一個元素,就要保證在刪除這個元素以前,這個元素不被其餘其餘元素引用(將引用這個元素的指針指向其餘元素或置空)