您好,登錄后才能下訂單哦!
本篇內容介紹了“JavaScript的垃圾回收機制與內存泄漏問題講解”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
常用的兩種算法:
引用計數(新版瀏覽器已棄用,棄用原因:會出現循環引用的情況,無法進行垃圾回收,導致內存泄漏)
標記清除
引用計數,顧名思義一個對象是否有指向它的引用,即看棧中是否有指向要釋放的該塊堆內存中的地址,如果沒有,則該塊內存是不需要的,可以進行釋放,即垃圾回收
下面引用大佬的一個簡短例子來說明情況
// 創建一個對象person,他有兩個指向屬性age和name的引用
var person = {
age: 12,
name: 'aaaa'
};
person.name = null; // 雖然name設置為null,但因為person對象還有指向name的引用,因此name不會回收
var p = person;
person = 1; //原來的person對象被賦值為1,但因為有新引用p指向原person對象,因此它不會被回收
p = null; //原person對象已經沒有引用,很快會被回收
缺點:引用計數有一個致命的問題,那就是循環引用
當兩個對象相互引用,盡管他們已不再使用,但是垃圾回收器不會進行回收,最終可能會導致內存泄露。
function cycle() {
var o1 = {};//1
var o2 = {};//1
o1.a = o2;//2
o2.a = o1; //2
return "cycle reference!"
}
cycle();
cycle
函數執行完成之后,對象o1
和o2
實際上已經不再需要了,但根據引用計數的原則,他們之間的相互引用依然存在,因此這部分內存不會被回收。所以現代瀏覽器不再使用這個算法。
但是IE依舊使用。
var div = document.createElement("div");div.onclick = function() { console.log("click");};
上面的寫法很常見,但是上面的例子就是一個循環引用。
變量div有事件處理函數的引用,同時事件處理函數也有div的引用,因為div變量可在函數內被訪問,所以循環引用就出現了。
文章里寫的是:標記清除算法將“不再使用的對象”定義為“無法到達的對象”。即從根部(在JS中就是全局對象)出發定時掃描內存中的對象,凡是能從根部到達的對象,保留。那些從根部出發無法觸及到的對象被標記為不再使用,稍后進行回收。
我這里個人理解:不在原型鏈上的,不能從全局對象鏈找到的對象,會被認為是無法到達的對象(也可能我自己理解有誤,忘讀者指出),比如說下面這個例子
var a = {} // 這里的a是掛在全局對象上的a = null // 這里a之前存放指向{}的地址變成了null// 此時{}是無法找到的,通過全局對象找到a也無法到達{},因此{}會被垃圾回收
無法觸及的對象包含了沒有引用的對象這個概念,但反之未必成立。
所以上面的例子就可以正確被垃圾回收處理了。
所以現在對于主流瀏覽器來說,只需要切斷需要回收的對象與根部的聯系,就能進行垃圾回收
下面還是引用大佬的例子
最常見的內存泄露一般都與DOM元素綁定有關:
email.message = document.createElement(“div”);
displayList.appendChild(email.message);
// 稍后從displayList中清除DOM元素
displayList.removeAllChildren();
上面代碼中,div
元素已經從DOM樹中清除,但是該div
元素還綁定在email對象中,所以如果email對象存在,那么該div
元素就會一直保存在內存中
“JavaScript的垃圾回收機制與內存泄漏問題講解”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。