標籤:move 前端開發 情況下 利用 span tle bag default jquery
作為程式員(更高大尚的稱謂:研軟體研發)的我們,無論是用Javascript,還是.net, java語言,肯定都遇到過記憶體流失的問題。只不過他們都有GC機制來協助程式員完成記憶體回收的事情,如果你是C++開發人員(你懂的)。。。。。,如果你是前端開發人員,肯定在使用Javascript(你或者會說,Js是世界上最棒的語言),但我這裡也得告訴你,Js的記憶體流失會來得更為突然,或者讓你都無法察覺。本文就帶大家領略一下Js的風騷:
一、模組化引起的記憶體流失
代碼如下:
// module date.jslet date = null;export default { init () { date = new Date(); }}// main.jsimport 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操作,那麼恭喜你,記憶體一定泄漏了。
Javascript的記憶體流失分析