亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

javascript有垃圾回收機制gc嗎

發布時間:2021-10-09 17:58:36 來源:億速云 閱讀:180 作者:栢白 欄目:web開發

今天小編給大家分享的是javascript有垃圾回收機制gc嗎,相信很多人都不太了解,為了讓大家更加了解,所以給大家總結了以下內容,一起往下看吧。一定會有所收獲的哦。

javascript中有GC(垃圾回收機制)。JavaScript是使用垃圾回收機制的語言,執行環境負責在代碼執行時管理內存,會自動將垃圾對象(沒有被引用的對象)從內存中銷毀。

JavaScript 中的垃圾回收機制(GC)

垃圾回收相關概念

① 什么是垃圾

沒有被使用(引用)的對象就是垃圾

② 什么是垃圾回收

沒有被引用的對象被銷毀,內存被釋放,就是垃圾回收

C、C++ 等編程語言需要手動垃圾回收。

Java、JavaScript、PHP、Python 等語言自動垃圾回收。

JS中擁有自動的垃圾回收機制,會自動將這些垃圾對象從內存中銷毀,我們不需要也不能進行垃圾回收的操作。我們需要做的只是要將不再使用的對象設置為 null 即可。

為什么需要垃圾回收

  • 在C / C++中,跟蹤內存的使用和管理內存對開發者來說是很大的負擔

    • JavaScript是使用垃圾回收機制的語言,也就是說執行環境負責在代碼執行時管理內存,幫開發者卸下了這個負擔

    • 通過自動內存管理實現內存的分配和資源的回收

    • 基本思路很簡單,確定哪個變量不會再被使用了,把它的內存空間釋放

    • 這個過程是周期性的,意思是這個垃圾回收程序每隔一段時間就會運行一次

  • 像JS中的對象、字符串、對象的內存是不固定的,只有真正用到的時候才會動態分配內存

    • 這些內存需在不使用后進行釋放以便再次使用,否則在計算機可用內存耗盡后造成崩潰

  • 瀏覽器發展史上的垃圾回收法主要有

    • 引用計數法

    • 標記清除法

引用計數法

思路

  • 變量只是對值進行引用

  • 當變量引用該值時,引用次數+1

  • 當該變量的引用被覆蓋或者清除時,引用次數-1

  • 當引用次數為0時,就可以安全地釋放這塊內存。

let arr = [1, 0, 1]   // [1, 0, 1]這塊內存被arr引用  引用次數為1
arr = [0, 1, 0]  // [1, 0, 1]的內存引用次數為0被釋放  
                 // [0, 1, 0]的內存被arr引用   引用次數為1
const tmp = arr  // [0, 1, 0]的內存被tmp引用   引用次數為2

循環引用問題

Netscape Navigator 3.0 采用

  • 在這個例子中,ObjectA和ObjectB的屬性分別相互引用

  • 造成這個函數執行后,Object被引用的次數不會變成0,影響了正常的GC。

  • 如果執行多次,將造成嚴重的內存泄漏。

  • 而標記清除法則不會出現這個問題。

function Example(){

    let ObjectA = new Object();
    let ObjectB = new Object();

    ObjectA.p = ObjectB;
    ObjectB.p = ObjectA;   

}

Example();
  • 解決方法:在函數結束時將其指向null

ObjectA = null;
ObjectB = null;

標記清除法

為了解決循環引用造成的內存泄漏問題,Netscape Navigator 4.0 開始采用標記清除法

到了 2008 年,IE、Firefox、Opera、Chrome 和 Safari 都在自己的 JavaScript 實現中采用標記清理(或 其變體),只是在運行垃圾回收的頻率上有所差異。

思路

  • 在變量進入執行上下文時打上“進入”標記

  • 同時在變量離開執行上下文時也打上“離開”標記

    • 從此以后,無法訪問這個變量

    • 在下一次垃圾回收時進行內存的釋放

function Example(n){
    const a = 1, b = 2, c = 3;
    return n * a * b * c;
}
// 標記Example進入執行上下文

const n = 1;  // 標記n進入執行上下文
Example(n);   // 標記a,b,c進入執行上下文
console.log(n); // 標記a, b, c離開執行上下文,等待垃圾回收

const和let聲明提升性能

  • const和let不僅有助于改善代碼風格,同時有利于垃圾回收性能的提升

  • const和let使JS有了塊級作用域,當塊級作用域比函數作用域更早結束時,垃圾回收程序更早介入

  • 盡早回收該回收的內存,提升了垃圾回收的性能

V8引擎的垃圾回收

V8引擎的垃圾回收采用標記清除法與分代回收法

分為新生代和老生代

新生代

新生代垃圾回收采用Scavenge 算法

分配給常用內存和新分配的小量內存

  • 內存大小

    • 32位系統16M內存

    • 64位系統32M內存

  • 分區

    • 新生代內存分為以下兩區,內存各占一半

    • From space

    • To space

  • 運行

    • 實際運行的只有From space

    • To space處于空閑狀態

  • Scavenge算法

    • 解決了內存散落分塊的問題(不連續的內存空間)

    • 相當于用空間換時間。

    • 當From space內存使用將要達到上限時開始垃圾回收,將From space中的不可達對象都打上標記

    • 將From space的未標記對象復制到To space。

    • 然后清空From space、將其閑置,也就是轉變為To space,俗稱反轉。

  • 新生代 -> 老生代

    • 內存大小達到From space的25%

    • 經歷了From space <-> To space的一個輪回

    • 新生代存放的是新分配的小量內存,如果達到以下條件中的一個,將被分配至老生代

老生代

老生代采用mark-sweep標記清除和mark-compact標記整理

通常存放較大的內存塊和從新生代分配過來的內存塊

  • 內存大小

    • 32位系統700M左右

    • 64位系統1.4G左右

  • 分區

    • 存儲編譯后的代碼

    • 存放存儲對象的映射關系

    • 存放其他區域放不下的較大的內存,基本都超過1M

    • 字面的老生代,存放的是新生代分配過來的內存。

    • Old Object Space

    • Large Object Space

    • Map Space

    • Code Space

  • 回收流程

    • 標記完成之后,將標記為1類的對象進行內存釋放

    • 采用深度優先遍歷,遍歷每個對象。

    • 首先將非根部對象全部標記為1類,然后進行深度優先遍歷。

    • 遍歷過程中將對象壓入棧,這個過程中對象被標記為2類

    • 遍歷完成對象出棧,這個對象被標記為3類

    • 整個過程直至棧空

    • 未被掃描,可回收,下面簡稱1類

    • 掃描中,不可回收,下面簡稱2類

    • 掃描完成,不可回收,下面簡稱3類

    • 標記分類(三色標記)

    • 遍歷

    • Mark-sweep

  • Mark-compact


    • 垃圾回收完成之后,內存空間是不連續的。

    • 這樣容易造成無法分配較大的內存空間的問題,從而觸發垃圾回收。

    • 所以,會有Mark-compact步驟將未被回收的內存塊整理為連續地內存空間。

    • 頻繁觸發垃圾回收會影響引擎的性能,內存空間不足時也會優先觸發Mark-compact

垃圾回收優化

  • 增量標記

    • 如果用集中的一段時間進行垃圾回收,新生代倒還好,老生代如果遍歷較大的對象,可能會造成卡頓。

    • 增量標記:使垃圾回收程序和應用邏輯程序交替運行,思想類似Time Slicing

  • 并行回收

    • 在垃圾回收的過程中,開啟若干輔助線程,提高垃圾回收效率。

  • 并發回收

    • 在邏輯程序執行的過程中,開啟若干輔助線程進行垃圾回收,清理和主線程沒有任何邏輯關系的內存。

內存泄露場景

全局變量

// exm1
function Example(){
    exm = 'LeBron'   
}

// exm2
function Example(){
    this.exm = 'LeBron'
}
Example()

未清除的定時器

const timer = setInterval(() => {
    //...
}, 1000)

// clearInterval(timer)

閉包

function debounce(fn, time) {
  let timeout = null; 
  return function () {
    if (timeout) {
      clearTimeout(timeout);
    }

    timeout = setTimeout(() => {
      fn.apply(this, arguments);
    }, time);
  };
}

const fn = debounce(handler, 1000); // fn引用了timeout

未清除的DOM元素引用

const element = {
    // 此處引用了DOM元素
    button:document.getElementById('LeBron'),
    select:document.getElementById('select')
}

document.body.removeChild(document.getElementById('LeBron'))

如何檢測內存泄漏

這個其實不難,瀏覽器原帶的開發者工具Performance就可以

  • 步驟

    • F12打開開發者工具

    • 選擇Performance工具欄

    • 勾選屏幕截圖和Memory

    • 點擊開始錄制

    • 一段時間之后結束錄制

  • 結果

    • 堆內存會周期性地分配和釋放

    • 如果堆內存的min值在逐漸上升則存在內存泄漏

優化內存使用

1、盡量不在for循環中定義函數

// exm
const fn = (idx) => {
    return idx * 2;
}

function Example(){
    for(let i=0;i<1000;i++){
        //const fn = (idx) => {
        //    return idx * 2;
        // }
        const res = fn(i);
    }
}

2、盡量不在for循環中定義對象

function Example() {
  const obj = {};
  let res = "";
  for (let i = 0; i < 1000; i++) {
    // const obj = {
    //   a: i,
    //   b: i * 2,
    //   c: i * 3,
    // };
    obj.a = i;
    obj.b = i * 2;
    obj.c = i * 3;
    res += JSON.stringify(obj);
  }
  return res
}

3、清空數組

arr = [0, 1, 2]
arr.length = 0; // 清空了數組,數組類型不變
// arr = []  // 重新申請了一塊空數組對象內存

關于javascript有垃圾回收機制gc嗎就分享到這里了,希望以上內容可以對大家有一定的參考價值,可以學以致用。如果喜歡本篇文章,不妨把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

广州市| 日照市| 喀喇| 拜城县| 洪泽县| 嘉峪关市| 鲁山县| 宜宾市| 利辛县| 福海县| 新乡县| 炎陵县| 澜沧| 德惠市| 内江市| 花莲县| 婺源县| 姜堰市| 兴山县| 新闻| 石柱| 龙里县| 高要市| 广丰县| 沧州市| 社会| 梧州市| 紫金县| 黔东| 老河口市| 新民市| 东乡族自治县| 元阳县| 石台县| 子长县| 定远县| 宣威市| 侯马市| 许昌市| 普格县| 仁布县|