Javascript的記憶體泄漏分析

来源:https://www.cnblogs.com/cqhaibin/archive/2018/07/08/9280753.html
-Advertisement-
Play Games

作為程式員(更高大尚的稱謂:研軟體研發)的我們,無論是用Javascript,還是.net, java語言,肯定都遇到過記憶體泄漏的問題。只不過他們都有GC機制來幫助程式員完成記憶體回收的事情,如果你是C++開發者(你懂的)。。。。。,如果你是前端開發者,肯定在使用Javascript(你或者會說,Js ...


     作為程式員(更高大尚的稱謂:研軟體研發)的我們,無論是用Javascript,還是.net, java語言,肯定都遇到過記憶體泄漏的問題。只不過他們都有GC機制來幫助程式員完成記憶體回收的事情,如果你是C++開發者(你懂的)。。。。。,如果你是前端開發者,肯定在使用Javascript(你或者會說,Js是世界上最棒的語言),但我這裡也得告訴你,Js的記憶體泄漏會來得更為突然,或者讓你都無法察覺。本文就帶大家領略一下Js的風騷:

一、模塊化引起的記憶體泄漏

代碼如下:

// module date.js
let date = null;
export default {
    init () {
        date = new Date();
    }
}

// main.js
import date from 'date.js';
date.init();

      上述是我們在現代前端工程方案中常見的代碼格式,寫一個模塊,然後導出這一個模塊。這裡你應該知道date.js中的date是靜態的(也就是你在N處導入date.js這個模塊),但他們的date這個變數是共用的,一處改變,其他地方也對應發生變化。

 

二、假OOP範式引起的記憶體泄漏

在這裡我為什麼叫他假OOP呢,原因是這代碼是想實現OOP範式卻讓自己掉到坑裡去了,先上代碼:

var fun = function(arg){
    this.sarg = arg; 
    var self = this;
    return function(){
        console.log(self.sarg);
    }
}
var fn = new fun('data arg');
fn();

首先,定義fun這個函數變數,然後返回一個function(這可以說就是典型的閉包)。閉包函數內引用外面的this對象(var self = this)。

然後,通過new的方式調用fun,返回值用fn接受,這裡誰都知道返回的是一個函數,所以可以括弧運算符進行執行。

2.1 利用chrome的memory面板進行分析

      定位到memory面板,然後刷新頁面,再單擊下圖中所示的 'collect garbage'圖標(也就是像回收站的圖標),強制進行一次gc的回收,這樣可以確保我們分析的對象就是可以存在記憶體泄漏的對象(至少他們是gc不可回收的對象)。

此圖是上述代碼片段在chrome瀏覽器中執行完成後,不能被gc回收的記憶體變數。

2.2 我認為的原因

先貼出發生記憶體泄漏的代碼

var fun = function(arg){
    this.sarg = arg; //記憶體泄漏
    var self = this;//記憶體泄漏
    return function(){
        console.log(self.sarg);//記憶體泄漏
    }
}
var fn = new fun('data arg'); //記憶體泄漏
fn();

我認為的原因有以下幾點:

1. 使用new運算符,他會創建一個對象,然後執行構造函數,並將構造函數對應的prototype(也就是原型)複製到新的對象上。

2. 上述new出來的新對象,在執行構造函數時,其this就指向了這個new出來的新對象

3. 然後上述代碼在構造函數中又返回了一個函數,且函數中引用了new出來的新對象,返回函數賦值給了fn變數

4. 最的執行fn變數,正確輸出我們想要的內容,這樣程式就跑了(可以,我們new出來的新對象,沒有人管也了,所以他就泄漏了)。

2.3 總結:

     因為正常情況下,我們對一個function進行new操作的時候,在構造函數內是不會進行返回的,其實這個時候new操作預設給你返回的就是構造函數中的this對象。上述代碼不建議出現在項目代碼中,這是典型的錯誤寫法,並示例只是為了演示泄漏。

 

三、DOM事件引起的記憶體泄漏

如果你是Jquery的忠粉,這部分可能對你有幫助,先上代碼:

//html:
<input type="file" id="file" />
<button type="button" onclick="remove()" >but</button>

//js:
var file = document.getElementById("file");
file.addEventListener('change',function(event){
    console.log(event.target.value);
});
function remove(){
    file.remove();
}

首先我們在html中寫兩個標簽,一個是file、一個是button;然後在js中對file標簽綁定了change事件,然後對button綁定一個remove方法,用於移除file標簽。

3.1 記憶體泄漏分析

在我們執行了remove方法後,然後收集記憶體分析:

     我們還按照示例二相同的操作,打開memory面板,然後執行一次GC回收後收集記憶體數據,然後查看Detached Dom tree(這就表示與DOM樹失去聯繫的對象),然後我們把滑鼠移動到native上,就會顯示記憶體泄漏的代碼位置。

Jquery忠粉們可以註意了,無論你是用的bind還是on進行事件的綁定,如果你在移除這些DOM元素前,沒有進行相應的unbind或是off操作,那麼恭喜你,記憶體一定泄漏了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • h5圖片獲取展示,非同步上傳至伺服器。( 如果有問題,歡迎留言 ^_^ ) ...
  • react有很多好玩的組件,react-grid-gallery就是其中一個,主要處理圖片展示,對圖片進行放大與縮小 文檔:https://www.npmjs.com/package/react-grid-gallery demo:https://benhowell.github.io/react- ...
  • 基本選擇器 回顧選擇器 通配符選擇器 元素選擇器 類選擇器 ID選擇器 後代選擇器 新增基本選擇器 子元素選擇器 相鄰兄弟選擇器 通用兄弟選擇器 群組選擇器 子元素選擇器 概念:子元素選擇器只能選擇某元素的子元素 語法:父元素 子元素 (Father Children) 相容性:IE8+、Firef ...
  • Sublime Text是一款輕量級的易於使用的前端編寫軟體,個人比較推薦。 找到Sublime的官網,下載對應的版本後,點擊安裝。安裝完成後需要下載相應的插件才能進行更加 有效率的開發工作。編寫前端的插件常用的就是Emmet。 首先在Sublime中使用快捷鍵ctrl+shift+p進入頁面,輸入 ...
  • 隨著業務的增加,可能存在這麼一種需求,就是需要從h5中直接跳轉到app。如果沒有安裝app的話,則提示到應用市場或者app store下載安裝。不過問題就在這個地方,單純的用h5是沒有方法判斷是否安裝過app的,不過這些是難不倒程式員的,他們通常會用這種代碼來解決 其實代碼很簡單,先去跳轉公司無線組 ...
  • 1.行內元素和塊級元素?img算什麼?行內元素怎麼轉化為塊級元素? 2.將多個元素設置為同一行?清除浮動有幾種方式? 3.怪異盒模型box-sizing?彈性盒模型|盒佈局? 4.簡述幾個css hack? 5.href和src區別? title和alt 6.transform?animation? ...
  • 最近新開了一個Node項目,採用TypeScript來開發,在資料庫及路由管理方面用了不少的裝飾器,發覺這的確是一個好東西。裝飾器是一個還處於草案中的特性,目前木有直接支持該語法的環境,但是可以通過 babel 之類的進行轉換為舊語法來實現效果,所以在TypeScript中,可以放心的使用@Deco ...
  • 1.viewport標簽 基本語法: <meta name=”viewport” content=”width=device-width,initial-scale=1” /> 上面這行代碼的意思是,面積的100%,網頁寬度預設等於屏幕寬度(width=device-width), 原始縮放比例(i ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...