垃圾回收:在不須要字符串、對象的時候,須要釋放其所佔用的內存。
高級語言解釋器嵌入了「垃圾回收器」,監控着全部對象,當對象生存週期結束時會將其刪除。
內嵌的垃圾回收器的問題:自動尋找是否一些內存「再也不須要」的問題是沒法斷定的。垃圾回收實現只能有限制的解決通常問題。因此引出垃圾回收算法(機制)。node
垃圾回收算法主要依賴於引用的概念。在內存管理的環境中,一個對象若是有訪問另外一個對象的權限(隱式或者顯式),叫作一個對象引用另外一個對象。例如,一個Javascript對象具備對它原型的引用(隱式引用)和對它屬性的引用(顯式引用)。算法
在這裏,「對象」的概念不只特指 JavaScript 對象,還包括函數做用域(或者全局詞法做用域)。segmentfault
垃圾回收算法的原理:垃圾收集器會按照固定的時間間隔,週期性的找出再也不繼續使用的變量,而後釋放其佔用的內存。
再也不使用的變量也就是生命週期結束的變量,是局部變量,局部變量只在函數的執行過程當中存在,當函數運行結束,沒有其餘引用(閉包),那麼該變量會被標記回收。全局變量不會被當成垃圾回收。數組
工做原理:
當變量進入環境時(例如在函數中聲明一個變量),將這個變量標記爲「進入環境」,當變量離開環境時,則將其標記爲「離開環境」。標記「離開環境」的就回收內存。瀏覽器
工做流程:閉包
內存泄漏:未能釋放再也不使用的內存,形成內存的浪費。
雖然有垃圾回收機制,但咱們在編寫代碼的時候,有些狀況仍是會形成內存泄漏,瞭解這些狀況,並在編寫程序的時候,注意避免,咱們的程序會更具健壯性。dom
全局變量不會被當成垃圾回收,咱們在編碼中有時會出現下面這種狀況:函數
function foo() { this.bar2 = '默認綁定this指向全局' // 全局變量=> window.bar2 bar = '全局變量'; // 沒有聲明變量 其實是全局變量=>window.bar } foo();
當咱們使用默認綁定,this會指向全局,this.something
也會建立一個全局變量,這一點可能不少人沒有注意到。this
解決方法:
1. 在函數內使用嚴格模式編碼
function foo() { "use strict"; this.bar2 = "嚴格模式下this指向undefined"; bar = "報錯"; } foo();
2.手動釋放全局變量的內存:
window.bar = undefined delete window.bar2
當不須要setInterval
或者setTimeout
時,定時器沒有被clear,定時器的回調函數以及內部依賴的變量都不能被回收,形成內存泄漏。
var someResource = getData(); setInterval(function() { var node = document.getElementById('Node'); if(node) { node.innerHTML = JSON.stringify(someResource)); // 定時器也沒有清除 } // node、someResource 存儲了大量數據 沒法回收 }, 1000);
解決方法: 在定時器完成工做的時候,手動清除定時器。
閉包能夠維持函數內局部變量,使其得不到釋放,形成內存泄漏。
function bindEvent() { var obj = document.createElement("XXX"); var unused = function () { console.log(obj,'閉包內引用obj obj不會被釋放'); }; // obj = null; }
解決方法:手動解除引用,obj = null
。
var refA = document.getElementById('refA'); document.body.removeChild(refA); // dom刪除了 console.log(refA, "refA"); // 可是還存在引用 能console出整個div 沒有被回收
不信的話,能夠看下這個dom點擊預覽。
解決辦法:refA = null;
過多的console,好比定時器的console會致使瀏覽器卡死。
解決辦法:合理利用console,線上項目儘可能少的使用console。
參考文章:https://segmentfault.com/a/11...
參考文章:https://segmentfault.com/a/11...