1. 程式人生 > >看完後你會明白什麼是垃圾回收機制

看完後你會明白什麼是垃圾回收機制

記憶體的生命週期:

  1. 分配你所需要的記憶體:

由於字串、物件等沒有固定的大小,js程式在每次建立字串、物件的時候,程式都會分配記憶體來儲存那個實體

  1. 使用分配到的記憶體做點什麼。

  2. 不需要時將其釋放回歸:

在不需要字串、物件的時候,需要釋放其所佔用的記憶體,否則將會消耗完系統中所有可用的記憶體,造成系統崩潰,這就是垃圾回收機制所存在的意義

所謂的記憶體洩漏指的是:由於疏忽或錯誤造成程式未能釋放那些已經不再使用的記憶體,造成記憶體的浪費。

垃圾回收機制:

在C和C++之類的語言中,需要手動來管理記憶體的,這也是造成許多不必要問題的根源。幸運的是,在編寫js的過程中,記憶體的分配以及記憶體的回收完全實現了自動管理,我們不用操心這種事情。

垃圾收集機制的原理:

垃圾收集器會按照固定的時間間隔,週期性的找出不再繼續使用的變數,然後釋放其佔用的記憶體

什麼叫不再繼續使用的變數?

不再使用的變數也就是生命週期結束的變數,是區域性變數,區域性變數只在函式的執行過程中存在,當函式執行結束,沒有其他引用(閉包),那麼該變數會被標記回收。

全域性變數的生命週期直至瀏覽器解除安裝頁面才會結束,也就是說全域性變數不會被當成垃圾回收

標記清除:當前採用的垃圾收集策略

工作原理:

當變數進入環境時(例如在函式中宣告一個變數),將這個變數標記為“進入環境”,當變數離開環境時,則將其標記為“離開環境”。標記“離開環境”的就回收記憶體。

工作流程:

  1. 垃圾收集器會在執行的時候會給儲存在記憶體中的所有變數都加上標記
  2. 去掉環境中的變數以及被環境中的變數引用的變數的標記。
  3. 那些還存在標記的變數被視為準備刪除的變數。
  4. 最後垃圾收集器會執行最後一步記憶體清除的工作,銷燬那些帶標記的值並回收它們所佔用的記憶體空間。

到2008年為止,IE、Chorme、Fireofx、Safari、Opera 都使用標記清除式的垃圾收集策略,只不過垃圾收集的時間間隔互有不同。

引用計數略:被廢棄的垃圾收集策

迴圈引用:跟蹤記錄每個值被引用的技術

在老版本的瀏覽器中(對,又是IE),IE9以下BOM和DOM物件就是使用C++以COM物件的形式實現的。

COM的垃圾收集機制採用的就是引用計數策略,這種機制在出現迴圈引用的時候永遠都釋放不掉記憶體。

var element = document.getElementById('something');
var myObject = new Object();
myObject.element = element; // element屬性指向dom
element.someThing = myObject; // someThing回指myObject 出現迴圈引用(兩個物件一直互相包含 一直存在計數)。

解決方式是,當我們不使用它們的時候,手動切斷連結:

myObject.element = null; 
element.someThing = null;

淘汰

IE9把BOM和DOM物件轉為了真正的js物件,避免了使用這種垃圾收集策略,消除了IE9以下常見的記憶體洩漏的主要原因。

IE7以下有一個宣告狼藉的效能問題,大家瞭解一下:

  1. 256個變數,4096個物件(或陣列)字面或者64KB的字串,達到任何一個臨界值會觸發垃圾收集器執行。
  2. 如果一個js指令碼的生命週期一直保有那麼多變數,垃圾收集器會一直頻繁的執行,引發嚴重的效能問題。

IE7已修復這個問題。

哪些情況會引起記憶體洩漏?

雖然有垃圾回收機制,但我們在編寫程式碼的時候,有些情況還是會造成記憶體洩漏,瞭解這些情況,並在編寫程式的時候,注意避免,我們的程式會更具健壯性。

意外的全域性變數:

上文我們提到了全域性變數不會被當成垃圾回收,我們在編碼中有時會出現下面這種情況:

function foo() {
 this.bar2 = '預設繫結this指向全域性' // 全域性變數=> window.bar2
  bar = '全域性變數'; // 沒有宣告變數 實際上是全域性變數=>window.bar
}
foo();

當我們使用預設繫結,this會指向全域性,this.something也會建立一個全域性變數,這一點可能很多人沒有注意到。

解決方法:在函式內使用嚴格模式or細心一點

function foo() {
  "use strict"; 
  this.bar2 = "嚴格模式下this指向undefined"; 
  bar = "報錯";
}
foo();

當然我們也可以手動釋放全域性變數的記憶體

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

迴圈引用問題

就是IE9以下的迴圈引用問題,上文講過了。

沒有清理DOM元素引用:

var refA = document.getElementById('refA');
document.body.removeChild(refA); // dom刪除了
console.log(refA, "refA");  // 但是還存在引用 能console出整個div 沒有被回收

不信的話,可以看下這個dom

解決辦法:refA = null;

console儲存大量資料在記憶體中。

過多的console,比如定時器的console會導致瀏覽器卡死。

解決:合理利用console,線上專案儘量少的使用console,當然如果你要發招聘,除外。

如何避免記憶體洩漏:

記住一個原則:不用的東西,及時歸還,畢竟你是’借的’嘛

  1. 減少不必要的全域性變數,使用嚴格模式避免意外建立全域性變數。
  2. 在你使用完資料後,及時解除引用(閉包中的變數,dom引用,定時器清除)。
  3. 組織好你的邏輯,避免死迴圈等造成瀏覽器卡頓,崩潰的問題。

關於記憶體洩漏:

  1. 即使是1byte的記憶體,也叫記憶體洩漏,並不一定是導致瀏覽器崩潰、卡頓才能叫做記憶體洩漏。
  2. 一般是堆區記憶體洩漏,棧區不會洩漏。

基本型別的值存在記憶體中,被儲存在棧記憶體中,引用型別的值是物件,儲存在堆記憶體中。所以物件、陣列之類的,才會發生記憶體洩漏


轉自:OBKoro1

http://obkoro1.com/2018/07/08/JS%E9%AB%98%E7%A8%8B%E4%B8%AD%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E4%B8%8E%E5%B8%B8%E8%A7%81%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/#more

相關推薦

明白什麼是垃圾回收機制

記憶體的生命週期:分配你所需要的記憶體:由於字串、物件等沒有固定的大小,js程式在每次建立字串、物件的時候,程式都會分配記憶體來儲存那個實體。使用分配到的記憶體做點什麼。不需要時將其釋放回歸:在不需要字串、物件的時候,需要釋放其所佔用的記憶體,否則將會消耗完系統中所有可用的記

這個明白什麼是愛情?什麼是婚姻?什麼是幸福?

有一天,柏拉圖問蘇格拉底:什麼是愛情? 蘇格拉底說:我請你穿越這片稻田,去摘一株最大最金黃的麥穗回來,但是有個規則:你不能走回頭路,而且你只能摘一次。 於是柏拉圖去做了。許久之後,他卻空著雙手回來了。 蘇格拉底問他怎麼空手回來了? 柏拉圖說道:當我走在田間的時候,曾看到過幾株

關於Linux訊號量的理解和探討(別說不懂,耐心恍然大悟~)

工作環境(藍色粗體字為特別注意內容) 1,實驗環境:Linux2.6 2,參考文獻:https://www.cnblogs.com/LZYY/p/3453582.html 最近在操作裝置檔案的時候,要求使用獨佔模式使用串列埠裝置,即一個程序用完之後釋放該串列埠,供其他程序使用。該如何實現該

MOS管與場效應晶體管背後的聯系,就全明白

blog field mark sem 比較 原理 c51 今天 頻率 電子元器件行業有今天的成就,那絕離不開MOS管與場效應晶體管的鼎力相助,但是一些剛入電子行業的常常把MOS管與場效應晶體管混為一談,到底MOS管和場效應晶體管兩者背後到底有何聯系?這對於初學者來說,這兩

ag視訊平臺網站作假是真的嗎,這些明白不可能作假的

應該 什麽 會有 並不是 玩家 速度 自己 自己的 問題 信譽首選【永久網址864968.C○㎡】AG真人視訊網站,首先你要明白ag是什麽,ag其實只做源頭,它沒有自己的網苔,這點一定要清楚,不要被一些詞語給蒙蔽了。如果理解了ag只是源頭的話,那就應該明白是怎麽回事了,作為

徹底理解 WebSocket 原理,附完整的實戰代碼(包含前端和端)

tcp 協議 learn php 握手 live 雙向 簡單 再次 註意 1、前言 最近有同學問我有沒有做過在線咨詢功能。同時,公司也剛好讓我接手一個 IM 項目。所以今天抽時間記錄一下最近學習的內容。本文主要剖析了 WebSocket 的原理,以及附上一個完整的聊天室實戰

#程式設計師剛寫程式碼就被開除了,網友:怎樣才能和一樣優秀

程式設計師這行業可能對於一般人來說,你不入這行,是不懂行裡的門道的。網際網路行業的迅猛發展,很多人都選擇加入到程式設計師這個群體中來,現在很多人都說該行業呈飽和狀態,畢竟一年百萬級的程式設計師加入進來。 在這裡我推薦下自己整理的資料,我自己是一名從事了5年java開發的全棧工程師,如果有

Python垃圾回收機制!非常實用!不過來!

python作為一門解釋型語言,以程式碼簡潔易懂著稱。我們可以直接對名稱賦值,而不必宣告型別。名稱型別的確定、記憶體空間的分配與釋放都是由python直譯器在執行時進行的。python這一自動管理記憶體功能極大的減小了程式設計師負擔,這也是成就python自身的重要原因之一。所以,這一篇文章我們就聊

這個還不 插入排序 麼

前言 由於LeetCode上的演算法題很多涉及到一些基礎的資料結構,為了更好的理解後續更新的一些複雜題目的動畫,推出一個新系列 -----《圖解資料結構》,主要使用動畫來描述常見的資料結構和演算法。本系列包括十大排序、堆、佇列、樹、並查集、圖等等大概幾十篇。 插入排序 插入排序的程式碼實現雖然沒有氣泡排

程式設計師剛寫程式碼就被開除了,網友:怎樣才能和一樣優秀

程式設計師這行業可能對於一般人來說,你不入這行,是不懂行裡的門道的。網際網路行業的迅猛發展,很多人都選擇加入到程式設計師這個群體中來,現在很多人都說該行業呈飽和狀態,畢竟一年百萬級的程式設計師加入進來。 在java吧看到這樣一個帖子: 樓主表示,剛寫完程式碼,就被開除了,是不是因為自己

不需要旋轉,卻能力壓群雄的資料結構——非旋Treap 還不打我

非旋Treap講解Treap,一種平衡樹。作為一棵平衡樹,一定是遵從著某種原則,使得這棵樹儘量的接近完全二叉樹。除了二叉搜尋樹都具備的性質——左子樹 ≤ 根 ≤ 右子樹,顧名思義,Treap = tree+heap。這時他的特殊性質就飄出水面了——heap。有一個需要慢慢理解

一堂價值39萬元的課,把它一定有收穫

和 別人發生意見上的紛歧,甚造成言語上的衝突,所以你悶悶不樂,因為你覺得都是別人惡意。別再耿耿於懷了,回家去擦地板吧。拎一塊抹布,彎下腰,雙膝著地, 把你面前這張地板的每個角落來回擦拭乾淨。然後重新省思自己在那場衝突,所說過的每一句話。現在,你發現自己其實也有不對的地方了,是不是?你漸漸心平氣 和了,是不是?

java中存在垃圾回收機制,但是還有內存泄漏的問題,原因是

java 自己 data .so 這樣的 即使 垃圾 ref stack 答案是肯定的,但不能拿這一句回答面試官的問題。分析:JAVA是支持垃圾回收機制的,在這樣的一個背景下,內存泄露又被稱為“無意識的對象保持”。如果一個對象引用被無意識地保留下來,那麽垃圾回收器不僅不會處

BIOS設置圖解教程-就沒有不明白的了

width 系統軟件 寫入 pci nal pla max 導致 出現 BIOS(基本輸入/輸出系統)是被固化在計算機CMOS RAM芯片中的一組程序,為計算機提供最初的、最直接的硬件控制。BIOS主要有兩類∶AWARD BIOS和AMI BIOS。正確設置BIOS可大大

徹底搞懂Websocket原理

找到 說了 成了 原理 兩層 cep 告訴 edi 純粹 偶然在知乎上看到一篇回帖,瞬間覺得之前看的那麽多資料都不及這一篇回帖讓我對 websocket 的認識深刻有木有。所以轉到我博客裏,分享一下。比較喜歡看這種博客,讀起來很輕松,不枯燥,沒有布道師的陣仗,純粹為分享。廢

就理解什麽是數據的全量、增量、差異備份了

-a 在一起 image 所有 play raw class 完整 splay 在很遠很遠的地方,有一個帳房先生。 他每天要記很多很多的賬單。 老先生一生謹慎,為了保證賬本的安全, 便找來三個徒弟幫忙來對賬本做備份, 這樣即使賬本丟失了, 也可以用備份的賬本繼續使用。

Windows PowerShell是啥?本文就懂它了

硬盤 目錄 string img ges name 一個數 線程級並行 $? 這篇文章主要介紹了Windows PowerShell是啥?Windows PowerShell是什麽?Windows PowerShell有哪些特性?Windows PowerShell有什麽用

轉--徹底搞懂Websocket原理

接下來 lur 耗資源 最終 ive img pro -- 傳遞 偶然在知乎上看到一篇回帖,瞬間覺得之前看的那麽多資料都不及這一篇回帖讓我對 websocket 的認識深刻有木有。所以轉到我博客裏,分享一下。比較喜歡看這種博客,讀起來很輕松,不枯燥,沒有布道師的陣仗,純粹為

如何恢復u盤誤刪文件,就不覺得自己很菜了

cover 查找 都是 U盤數據恢復 uga jpeg 數據 硬盤 數據恢復 在工作和生活中,U盤發揮著不可替代的作用,別看它體積小,但是卻能保存大量的數據,厲害著呢。但是一切都是兩面的,U盤雖然能保存很多數據,但是卻不能讓數據一直安全的存在,一個不小心就能將文件刪除。 U

國服最強JWT生成Token做登錄校驗講解,保證學會!

共享 jwt 存儲 node 基於 clas 成功 講解 算法 轉載於:https://blog.csdn.net/u011277123/article/details/78918390Free碼農 2017-12-28 00:08:02 JWT簡介 JWT(j