欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

跟我學習javascript的垃圾回收機制與內存管理

 更新時間:2015年11月23日 14:41:13   作者:小平果118  
跟我學習javascript的垃圾回收機制與內存管理,感興趣的小伙伴們可以參考一下

一、垃圾回收機制—GC

Javascript具有自動垃圾回收機制(GC:Garbage Collecation),也就是說,執(zhí)行環(huán)境會負責管理代碼執(zhí)行過程中使用的內存。

原理:垃圾收集器會定期(周期性)找出那些不在繼續(xù)使用的變量,然后釋放其內存。

JavaScript垃圾回收的機制很簡單:找出不再使用的變量,然后釋放掉其占用的內存,但是這個過程不是實時的,因為其開銷比較大,所以垃圾回收器會按照固定的時間間隔周期性的執(zhí)行。

不再使用的變量也就是生命周期結束的變量,當然只可能是局部變量,全局變量的生命周期直至瀏覽器卸載頁面才會結束。局部變量只在函數的執(zhí)行過程中存在,而在這個過程中會為局部變量在?;蚨焉戏峙湎鄳目臻g,以存儲它們的值,然后在函數中使用這些變量,直至函數結束,而閉包中由于內部函數的原因,外部函數并不能算是結束。

還是上代碼說明吧:

function fn1() {
 var obj = {name: 'hanzichi', age: 10};
}

function fn2() {
 var obj = {name:'hanzichi', age: 10};
 return obj;
}

var a = fn1();
var b = fn2();

我們來看代碼是如何執(zhí)行的。首先定義了兩個function,分別叫做fn1和fn2,當fn1被調用時,進入fn1的環(huán)境,會開辟一塊內存存放對象{name: 'hanzichi', age: 10},而當調用結束后,出了fn1的環(huán)境,那么該塊內存會被js引擎中的垃圾回收器自動釋放;在fn2被調用的過程中,返回的對象被全局變量b所指向,所以該塊內存并不會被釋放。

這里問題就出現了:到底哪個變量是沒有用的?所以垃圾收集器必須跟蹤到底哪個變量沒用,對于不再有用的變量打上標記,以備將來收回其內存。用于標記的無用變量的策略可能因實現而有所區(qū)別,通常情況下有兩種實現方式:標記清除和引用計數。引用計數不太常用,標記清除較為常用。

二、標記清除

js中最常用的垃圾回收方式就是標記清除。當變量進入環(huán)境時,例如,在函數中聲明一個變量,就將這個變量標記為“進入環(huán)境”。從邏輯上講,永遠不能釋放進入環(huán)境的變量所占用的內存,因為只要執(zhí)行流進入相應的環(huán)境,就可能會用到它們。而當變量離開環(huán)境時,則將其標記為“離開環(huán)境”。

function test(){
 var a = 10 ; //被標記 ,進入環(huán)境 
 var b = 20 ; //被標記 ,進入環(huán)境
}
test(); //執(zhí)行完畢 之后 a、b又被標離開環(huán)境,被回收。

  垃圾回收器在運行的時候會給存儲在內存中的所有變量都加上標記(當然,可以使用任何標記方式)。然后,它會去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標記(閉包)。而在此之后再被加上標記的變量將被視為準備刪除的變量,原因是環(huán)境中的變量已經無法訪問到這些變量了。最后,垃圾回收器完成內存清除工作,銷毀那些帶標記的值并回收它們所占用的內存空間。

  到目前為止,IE、Firefox、Opera、Chrome、Safari的js實現使用的都是標記清除的垃圾回收策略或類似的策略,只不過垃圾收集的時間間隔互不相同。

三、引用計數

  引用計數的含義是跟蹤記錄每個值被引用的次數。當聲明了一個變量并將一個引用類型值賦給該變量時,則這個值的引用次數就是1。如果同一個值又被賦給另一個變量,則該值的引用次數加1。相反,如果包含對這個值引用的變量又取得了另外一個值,則這個值的引用次數減1。當這個值的引用次數變成0時,則說明沒有辦法再訪問這個值了,因而就可以將其占用的內存空間回收回來。這樣,當垃圾回收器下次再運行時,它就會釋放那些引用次數為0的值所占用的內存。

function test(){
 var a = {} ; //a的引用次數為0 
 var b = a ; //a的引用次數加1,為1 
 var c =a; //a的引用次數再加1,為2
 var b ={}; //a的引用次數減1,為1
}

  Netscape Navigator3是最早使用引用計數策略的瀏覽器,但很快它就遇到一個嚴重的問題:循環(huán)引用。循環(huán)引用指的是對象A中包含一個指向對象B的指針,而對象B中也包含一個指向對象A的引用。

function fn() {
 var a = {};
 var b = {};
 a.pro = b;
 b.pro = a;
}

fn();

  以上代碼a和b的引用次數都是2,fn()執(zhí)行完畢后,兩個對象都已經離開環(huán)境,在標記清除方式下是沒有問題的,但是在引用計數策略下,因為a和b的引用次數不為0,所以不會被垃圾回收器回收內存,如果fn函數被大量調用,就會造成內存泄露。在IE7與IE8上,內存直線上升。

我們知道,IE中有一部分對象并不是原生js對象。例如,其內存泄露DOM和BOM中的對象就是使用C++以COM對象的形式實現的,而COM對象的垃圾回收機制采用的就是引用計數策略。因此,即使IE的js引擎采用標記清除策略來實現,但js訪問的COM對象依然是基于引用計數策略的。換句話說,只要在IE中涉及COM對象,就會存在循環(huán)引用的問題。

var element = document.getElementById("some_element");
var myObject = new Object();
myObject.e = element;
element.o = myObject;

  這個例子在一個DOM元素(element)與一個原生js對象(myObject)之間創(chuàng)建了循環(huán)引用。其中,變量myObject有一個名為element的屬性指向element對象;而變量element也有一個屬性名為o回指myObject。由于存在這個循環(huán)引用,即使例子中的DOM從頁面中移除,它也永遠不會被回收。

看上面的例子,有同學回覺得太弱了,誰會做這樣無聊的事情,其實我們是不是就在做

window.onload=function outerFunction(){
 var obj = document.getElementById("element");
 obj.onclick=function innerFunction(){};
};

這段代碼看起來沒什么問題,但是obj引用了document.getElementById(“element”),而document.getElementById(“element”)的onclick方法會引用外部環(huán)境中德變量,自然也包括obj,是不是很隱蔽啊。

解決辦法

最簡單的方式就是自己手工解除循環(huán)引用,比如剛才的函數可以這樣

myObject.element = null;
element.o = null;


window.onload=function outerFunction(){
 var obj = document.getElementById("element");
 obj.onclick=function innerFunction(){};
 obj=null;
};

將變量設置為null意味著切斷變量與它此前引用的值之間的連接。當垃圾回收器下次運行時,就會刪除這些值并回收它們占用的內存。

要注意的是,IE9+并不存在循環(huán)引用導致Dom內存泄露問題,可能是微軟做了優(yōu)化,或者Dom的回收方式已經改變

四、內存管理

1、什么時候觸發(fā)垃圾回收?

垃圾回收器周期性運行,如果分配的內存非常多,那么回收工作也會很艱巨,確定垃圾回收時間間隔就變成了一個值得思考的問題。IE6的垃圾回收是根據內存分配量運行的,當環(huán)境中存在256個變量、4096個對象、64k的字符串任意一種情況的時候就會觸發(fā)垃圾回收器工作,看起來很科學,不用按一段時間就調用一次,有時候會沒必要,這樣按需調用不是很好嗎?但是如果環(huán)境中就是有這么多變量等一直存在,現在腳本如此復雜,很正常,那么結果就是垃圾回收器一直在工作,這樣瀏覽器就沒法兒玩兒了。

微軟在IE7中做了調整,觸發(fā)條件不再是固定的,而是動態(tài)修改的,初始值和IE6相同,如果垃圾回收器回收的內存分配量低于程序占用內存的15%,說明大部分內存不可被回收,設的垃圾回收觸發(fā)條件過于敏感,這時候把臨街條件翻倍,如果回收的內存高于85%,說明大部分內存早就該清理了,這時候把觸發(fā)條件置回。這樣就使垃圾回收工作職能了很多

2、合理的GC方案

1)、Javascript引擎基礎GC方案是(simple GC):mark and sweep(標記清除),即:

  • (1)遍歷所有可訪問的對象。
  • (2)回收已不可訪問的對象。

2)、GC的缺陷

和其他語言一樣,javascript的GC策略也無法避免一個問題:GC時,停止響應其他操作,這是為了安全考慮。而Javascript的GC在100ms甚至以上,對一般的應用還好,但對于JS游戲,動畫對連貫性要求比較高的應用,就麻煩了。這就是新引擎需要優(yōu)化的點:避免GC造成的長時間停止響應。

3)、GC優(yōu)化策略

David大叔主要介紹了2個優(yōu)化方案,而這也是最主要的2個優(yōu)化方案了:

(1)分代回收(Generation GC)
這個和Java回收策略思想是一致的。目的是通過區(qū)分“臨時”與“持久”對象;多回收“臨時對象”區(qū)(young generation),少回收“持久對象”區(qū)(tenured generation),減少每次需遍歷的對象,從而減少每次GC的耗時。如圖:

這里需要補充的是:對于tenured generation對象,有額外的開銷:把它從young generation遷移到tenured generation,另外,如果被引用了,那引用的指向也需要修改。

(2)增量GC
這個方案的思想很簡單,就是“每次處理一點,下次再處理一點,如此類推”。如圖:

這種方案,雖然耗時短,但中斷較多,帶來了上下文切換頻繁的問題。

因為每種方案都其適用場景和缺點,因此在實際應用中,會根據實際情況選擇方案。

比如:低 (對象/s) 比率時,中斷執(zhí)行GC的頻率,simple GC更低些;如果大量對象都是長期“存活”,則分代處理優(yōu)勢也不大。

參考:

以上就是關于javascript的垃圾回收機制與內存管理的全部內容,希望對大家的學習有所幫助。

相關文章

  • js克隆對象、數組的常用方法介紹

    js克隆對象、數組的常用方法介紹

    以下幾種方法都是復制一個新的對象或者數組,但是如果直接通過parent【iframe情況】的方式去父窗口的對象的時候會有問題,感興趣的朋友可以了解下
    2013-09-09
  • JavaScript簡單實現的仿微博留言功能示例

    JavaScript簡單實現的仿微博留言功能示例

    這篇文章主要介紹了JavaScript簡單實現的仿微博留言功能,涉及javascript頁面元素屬性動態(tài)操作相關實現技巧,需要的朋友可以參考下
    2019-01-01
  • 關于window.pageYOffset和document.documentElement.scrollTop

    關于window.pageYOffset和document.documentElement.scrollTop

    window.pageYOffset:Netscape屬性,指的是滾動條頂部到網頁頂部的距離
    2011-04-04
  • layui動態(tài)加載多表頭的實例

    layui動態(tài)加載多表頭的實例

    今天小編就為大家分享一篇layui動態(tài)加載多表頭的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • js特效,頁面下雪的小例子

    js特效,頁面下雪的小例子

    js特效,頁面下雪的小例子,需要的朋友可以參考一下
    2013-06-06
  • javascript利用canvas實現鼠標拖拽功能

    javascript利用canvas實現鼠標拖拽功能

    這篇文章主要為大家詳細介紹了javascript利用canvas實現鼠標拖拽功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • js+CSS簡單實現瀑布流布局

    js+CSS簡單實現瀑布流布局

    瀑布流布局,是一種視覺表現為參差不齊的多欄布局,常用于內容以圖片為主的頁面展示,本文將使用css和js兩種方式來實現瀑布流布局,需要的可以參考下
    2023-11-11
  • js實現隨機數小游戲

    js實現隨機數小游戲

    這篇文章主要為大家詳細介紹了js實現隨機數小游戲,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • js實現按鈕加背景圖片常用方法

    js實現按鈕加背景圖片常用方法

    這篇文章主要介紹了js實現按鈕加背景圖片常用方法,羅列了js事件觸發(fā)控制背景圖片、css樣式控制以及圖片按鈕三種方法,非常具有實用價值,需要的朋友可以參考下
    2014-11-11
  • 使用js去除字符串內所帶有空格的三種方法

    使用js去除字符串內所帶有空格的三種方法

    在前端開發(fā)的過程中,我們經常會遇到需要對于輸入的字符串進行格式化處理,這篇文章主要給大家介紹了關于使用js去除字符串內所帶有空格的三種方法,需要的朋友可以參考下
    2023-10-10

最新評論