前端面試查漏補缺--(十三) 內存泄漏

前言

本系列最開始是爲了本身面試準備的.後來發現整理愈來愈多,差很少有十二萬字符,最後決定仍是分享出來給你們.html

爲了分享整理出來,花費了本身大量的時間,起碼是隻本身用的三倍時間.若是喜歡的話,歡迎收藏,關注我!謝謝!前端

文章連接

合集篇:

前端面試查漏補缺--Index篇(12萬字符合集) 包含目前已寫好的系列其餘十幾篇文章.後續新增值文章不會再在每篇添加連接,強烈建議議點贊,關注合集篇!!!!,謝謝!~vue

後續更新計劃

後續還會繼續添加設計模式,前端工程化,項目流程,部署,閉環,vue常考知識點 等內容.若是以爲內容不錯的話歡迎收藏,關注我!謝謝!node

求一分內推

目前本人也在準備跳槽,但願各位大佬和HR小姐姐能夠內推一份靠譜的武漢 前端崗位!郵箱:bupabuku@foxmail.com.謝謝啦!~git

什麼是內存泄漏?

程序的運行須要內存。只要程序提出要求,操做系統或者運行時(runtime)就必須供給內存。github

對於持續運行的服務進程(daemon),必須及時釋放再也不用到的內存。不然,內存佔用愈來愈高,輕則影響系統性能:變慢,延遲大等 ,重則致使進程崩潰。面試

再也不用到的內存,沒有及時釋放,就叫作內存泄漏(memory leak)。算法

內存泄漏的識別方法

  1. 使用快捷鍵 F12 或者 Ctrl+Shift+J 打開 Chrome 瀏覽器的「開發者工具」。設計模式

  2. 選擇 Performance(老版爲Timeline) 選項卡,在 Capture 選項中,只勾選 Memory前端工程化

  3. 設置完成後,點擊最左邊的 Record 按鈕,而後就能夠訪問網頁了。

  4. 打開一個網站,例如:www.taobao.com,當網頁加載完成後,點擊 Stop,等待分析結果。

  5. 而後在 Chart View 上尋找內存急速降低的部分,查看對應的 Event Log,能夠從中找到 GC 的日誌。

具體過程以下圖所示:

內存泄露的常見緣由及處理方式

常見緣由:

1. 意外的全局變量

下面代碼中變量bar在foo函數內,可是bar並無聲明.JS就會默認將它變爲全局變量,這樣在頁面關閉以前都不會被釋放.

function foo(){
    bar=2
    console.log('bar沒有被聲明!')
}
複製代碼

b 沒被聲明,會變成一個全局變量,在頁面關閉以前不會被釋放.使用嚴格模式能夠避免.

2. dom清空時,還存在引用

不少時候,爲了方便存取,常常會將 DOM 結點暫時存儲到數據結構中.可是在不須要該DOM節點時,忘記解除對它的引用,則會形成內存泄露.

var element = {
  shotCat: document.getElementById('shotCat')
};

document.body.removeChild(document.getElementById('shotCat'));
// 若是element沒有被回收,這裏移除了 shotCat 節點也是沒用的,shotCat 節點依然留存在內存中.
複製代碼

與此相似情景還有: DOM 節點綁定了事件, 可是在移除的時候沒有解除事件綁定,那麼僅僅移除 DOM 節點也是沒用的

3. 定時器中的內存泄漏

var someResource = getData();
setInterval(function() {
    var node = document.getElementById('Node');
    if(node) {
        node.innerHTML = JSON.stringify(someResource));
    }
}, 1000);
複製代碼

若是沒有清除定時器,那麼 someResource 就不會被釋放,若是恰好它又佔用了較大內存,就會引起性能問題. 可是 setTimeout ,它計時結束後它的回調裏面引用的對象佔用的內存是能夠被回收的. 固然有些場景 setTimeout 的計時可能很長, 這樣的狀況下也是須要歸入考慮的.

4. 不規範地使用閉包

例以下面的例子: 相互循環引用.這是常常容易犯的錯誤,而且有時也不容易發現.

function foo() { 
  var a = {}; 
  function bar() { 
    console.log(a); 
  }; 
  a.fn = bar; 
  return bar; 
};
複製代碼

bar和a造成了相互循環引用.可能有人說bar裏不使用console.log(a)不就沒有引用了嗎就不會形成內存泄露了.NONONO,bar做爲一個閉包,即便它內部什麼都沒有,foo中的全部變量都仍是隱式地被 bar所引用。 即便bar內什麼都沒有仍是形成了循環引用,那真正的解決辦法就是,不要將a.fn = bar.

避免策略:

  1. 減小沒必要要的全局變量,或者生命週期較長的對象,及時對無用的數據進行垃圾回收(即賦值爲null);
  2. 注意程序邏輯,避免「死循環」之類的 ;
  3. 避免建立過多的對象 原則:不用了的東西要記得及時歸還。
  4. 減小層級過多的引用

Node中的內存泄漏

node中的內存泄露與JS中的處理方法稍有不一樣,詳細能夠查看這篇文章,很是的詳細!

感謝及參考

相關文章
相關標籤/搜索