閉包 是指有權訪問另外一個函數做用域中的變量的函數,建立閉包最多見的方式就是在一個函數內部建立l另外一個函數,經過另外一個函數訪問這個函數的局部變量git
主要應用閉包的場合:設計私有的方法和變量github
閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題。瀏覽器
在IE中可能致使內存泄露。解決方法是,在退出函數以前,將不使用的局部變量所有刪除。閉包
在 IE8 如下的版本里,DOM 對象常常會跟 JavaScript 之間產生循環引用。就會形成內存泄漏:函數
function closure() { var element = document.getElementById('someElement'); element.onclick = function(){ alert(element.id) // 這裏致使element一直存在內存中 } }
應該將element解除引用來避免內存泄漏性能
function closure() { var element = document.getElementById('someElement'); var test = element.id element.onclick = function(){ alert(test) // 這裏致使element一致存在內存中 } element = null }
看完內存泄漏須要瞭解下JavaScript的垃圾回收機制,首先JavaScript具備自動垃圾回收機制,會找出再也不使用的變量,而後釋放其佔用的內存。經常使用的方法有兩種,即標記清除和引用計數設計
語言引擎有一張引用表,保存了內存裏面全部的資源(各類值)的引用次數。若是一個值的引用次數爲0,就表示這個值再也不用到了,所以就能夠將這塊內存釋放。可是引用計數有個最大的問題: 循環引用。code
function func() { let obj1 = {}; let obj2 = {}; obj1.a = obj2; // obj1 引用 obj2 obj2.a = obj1; // obj2 引用 obj1 }
當函數 func 執行結束後,返回值爲 undefined,因此整個函數以及內部的變量都應該被回收,但根據引用計數方法,obj1 和 obj2 的引用次數都不爲 0,因此他們不會被回收。對象
要解決循環引用的問題,最好是在不使用它們的時候手工將它們設爲空。上面的例子能夠這麼作:ip
obj1 = null; obj2 = null;
JavaScript 中有個全局對象,瀏覽器中是 window。按期的,垃圾回收期將從這個全局對象開始,找全部從這個全局對象開始引用的對象,再找這些對象引用的對象...對這些活着的對象進行標記,這是標記階段。清除階段就是清除那些沒有被標記的對象。
閉包只會在IE8如下的版本中才有可能形成內存泄漏問題,在最新版本的瀏覽器中,能夠經過標記清除的方式處理掉內存泄漏,不過閉包的變量會常駐內存,會形成必定的性能問題。