最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文詳解Javascript內(nèi)存機(jī)制與垃圾回收

 更新時(shí)間:2023年06月15日 10:32:49   作者:越谷  
這篇文章主要給大家詳細(xì)介紹了Javascript的內(nèi)存機(jī)制與垃圾回收,文中又詳細(xì)的代碼示例,對(duì)我們學(xué)習(xí)Javascript有一定的幫助,需要的同學(xué)可以借鑒閱讀

一 內(nèi)存機(jī)制

1.1 數(shù)據(jù)類型

Javascript 是一種動(dòng)態(tài)的(在運(yùn)行過程中檢查數(shù)據(jù)類型,)、弱類型(同一個(gè)變量可以保存不同類型的數(shù)據(jù))的語(yǔ)言。

Javascript 數(shù)據(jù)類型一共有 8 種: Boolean,Null,Undefined,Number,BigInt,String,Symbol,Object。前 7 種數(shù)據(jù)類型為原始類型Object引用類型。兩種類型的數(shù)據(jù)在內(nèi)存中存放的位置不同。

1.2 內(nèi)存空間

Javascript 在執(zhí)行的過程中,主要有三種類型的內(nèi)存空間,分別是:代碼空間、棧空間、堆空間。

代碼空間主要是存儲(chǔ)可執(zhí)行代碼的。

原始數(shù)據(jù)類型存儲(chǔ)在??臻g中, 引用數(shù)據(jù)類型存儲(chǔ)在堆空間中。

說(shuō)明示例:

function foo(){
    var a = "極客時(shí)間"
    var b = a
    var c = {name:"極客時(shí)間"}
    var d = c
}
foo()

??臻g,也就是之前提起的調(diào)用棧,用來(lái)存儲(chǔ)執(zhí)行上下文。

上述代碼執(zhí)行到第 3 行的時(shí)候,變量 a 和 b 的值都直接保存在執(zhí)行上下文中,執(zhí)行上下文又被壓入??臻g中,所以可以理解為變量 a 和 b 都存放在??臻g中。

當(dāng)執(zhí)行到第 4 行,Javascript 引擎判斷變量 c 的值是引用類型,Javascript 引擎將該值分配到堆空間里,分配后該值會(huì)有一個(gè)在堆空間的地址,然后將該地址賦值給變量 c。第 5 行,將 c 賦值給 d,實(shí)際是將引用地址賦值給了 d,修改引用類型對(duì)象的值,改的是堆空間中數(shù)據(jù)的值。

棧空間因?yàn)橐S護(hù)執(zhí)行上下文,影響程序的執(zhí)行效率,所以空間一般比較小,可以用來(lái)存放原始類型的小數(shù)據(jù);引用類型的數(shù)據(jù)可以很大,所以堆空間比較大,不過堆空間分配內(nèi)存和回收內(nèi)存會(huì)占用一定的時(shí)間。

棧空間切換執(zhí)行上下文狀態(tài):

1.3 閉包內(nèi)的數(shù)據(jù)存儲(chǔ)

閉包內(nèi)的變量存儲(chǔ)到??臻g還是堆空間?

說(shuō)明示例:

function foo() {
    var myName = "極客時(shí)間"
    let test1 = 1
    const test2 = 2
    var innerBar = { 
        setName:function(newName){
            myName = newName
        },
        getName:function(){
            console.log(test1)
            return myName
        }
    }
    return innerBar
}
var bar = foo()
bar.setName("極客邦")
bar.getName()
console.log(bar.getName())

執(zhí)行上述代碼,當(dāng) foo 函數(shù)執(zhí)行完之后,調(diào)用棧中的 foo 函數(shù)的執(zhí)行上下文會(huì)被銷毀,由于變量 myName 和 test1 持續(xù)存在外部引用,Javascript 引擎判斷這是一個(gè)閉包,會(huì)在堆空間中創(chuàng)建一個(gè)closure(foo)的對(duì)象,這個(gè)對(duì)象中包含這兩個(gè)被引用的變量。

二 垃圾回收

一些數(shù)據(jù)在使用后就不再需要了,這部分?jǐn)?shù)據(jù)繼續(xù)存在內(nèi)存里,并且逐漸積累,會(huì)占用越來(lái)越多的空間,通過垃圾回收機(jī)制以釋放有限的內(nèi)存空間。

2.1 不同語(yǔ)言的垃圾回收策略

一般,垃圾回收分為手動(dòng)回收自動(dòng)回收兩種策略。

以 C / C++ 為例,使用的是手動(dòng)回收策略,內(nèi)存的分配與銷毀都是由程序員寫的代碼控制的,如果不主動(dòng)銷毀垃圾數(shù)據(jù),將導(dǎo)致內(nèi)存泄漏。

以 Javascript / Java 為例,垃圾數(shù)據(jù)由內(nèi)置的垃圾回收器自動(dòng)回收,不需要通過編寫代碼手動(dòng)釋放。

2.2 調(diào)用棧的垃圾回收機(jī)制

Javascript 引擎把執(zhí)行上下文壓入調(diào)用棧的同時(shí),使用一個(gè)記錄當(dāng)前執(zhí)行狀態(tài)的指針(ESP)指向當(dāng)前的執(zhí)行上下文,表示正在執(zhí)行該執(zhí)行上下文。

當(dāng)該執(zhí)行上下文運(yùn)行完畢,ESP 下移,這個(gè)下移的操作就是銷毀被執(zhí)行過的上下文的過程。

示例說(shuō)明:

function foo(){
    var a = 1
    var b = {name:"極客邦"}
    function showName(){
      var c = 2
      var d = {name:"極客時(shí)間"}
    }
    showName()
}
foo()

2.3 堆空間垃圾回收機(jī)制

2.3.1 代際假說(shuō)

代際假說(shuō)觀點(diǎn)認(rèn)為,大部分對(duì)象在內(nèi)存中有用的時(shí)間很短,一經(jīng)分配內(nèi)存,很快就變得不可訪問;少量數(shù)據(jù)持續(xù)活躍,活的很久。

2.3.2 V8 垃圾回收機(jī)制:分代收集

基于代際假說(shuō),V8 把堆分為老生代新生代,新生代中存放的是生存時(shí)間短的對(duì)象(1—8M空間),老生代中存放的是生存時(shí)間久的對(duì)象(空間比較大)。

針對(duì)新生代和老生代,V8 使用不用的回收機(jī)制,以便更高效的進(jìn)行垃圾回收。使用主垃圾回收器回收老生代的垃圾數(shù)據(jù),使用副垃圾回收器回收新生代的垃圾數(shù)據(jù)。

垃圾回收原理

  • 標(biāo)記空間中的活動(dòng)對(duì)象(還在使用的對(duì)象)和非活動(dòng)對(duì)象(可以回收的對(duì)象)。
  • 標(biāo)記完成之后,統(tǒng)一清理內(nèi)存中所有被標(biāo)記的可回收對(duì)象,回收這部分對(duì)象占據(jù)的內(nèi)存。
  • 內(nèi)存整理:頻繁回收對(duì)象之后,內(nèi)存中存在大量不連續(xù)空間(內(nèi)存碎片),如果要分配較大連續(xù)內(nèi)存時(shí),可能出現(xiàn)內(nèi)存不足的情況,所以需要將內(nèi)存碎片成連續(xù)的空間。

副垃圾回收器

主要負(fù)責(zé)新生代的垃圾回收。新生代空間較小,里面的對(duì)象一般較小;回收頻繁。

回收機(jī)制采用 Scavenge 算法。該算法把新生代空間劃半分為對(duì)象區(qū)域空閑區(qū)域。

新加入的對(duì)象存到對(duì)象區(qū)域,當(dāng)對(duì)象區(qū)域快被寫滿時(shí),執(zhí)行一次垃圾回收。在回收過程中,對(duì)對(duì)象區(qū)域里的對(duì)象做標(biāo)記,標(biāo)記完成后,把存活的對(duì)象復(fù)制到空閑區(qū)域中并有序的排列起來(lái)(消除內(nèi)存碎片),把無(wú)用的對(duì)象清理掉。

復(fù)制完成后,對(duì)象區(qū)域和空閑區(qū)域進(jìn)行角色翻轉(zhuǎn),對(duì)象區(qū)域變成空閑區(qū)域,空閑區(qū)域變成對(duì)象區(qū)域。這樣這兩塊區(qū)域可以無(wú)限重復(fù)使用下去。

復(fù)制操作需要時(shí)間成本,因此為了執(zhí)行效率,新生區(qū)的空間一般設(shè)置的比較小。

經(jīng)過兩次垃圾回收依然存活的對(duì)象,會(huì)被移動(dòng)到老生區(qū)中,以防止過多的存活對(duì)象擠滿新生區(qū)。

主垃圾回收器

主要負(fù)責(zé)老生區(qū)的垃圾回收。老生區(qū)的里的對(duì)象一般占用空間大(因復(fù)制操作耗時(shí)所以不適合使用 Scavenge 算法),存活的時(shí)間比較長(zhǎng)。

回收機(jī)制采用的是 標(biāo)記-清除(Mark-Sweep)算法。從一組根元素開始,遞歸遍歷這組根元素,在遍歷過程中能到達(dá)的元素稱為活動(dòng)對(duì)象,沒有達(dá)到的元素判斷標(biāo)記為垃圾數(shù)據(jù)。

標(biāo)記完成之后,執(zhí)行清除過程。

如上圖,清除后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片;為了避免內(nèi)存碎片,進(jìn)化出了另一種算法:標(biāo)記-整理(Mark-Compact),標(biāo)記完成后,讓所有存活的對(duì)象移向內(nèi)存一端,然后直接清理掉端邊界外的數(shù)據(jù)。

全停頓

Javascript 是運(yùn)行在主線程上的(單線程),一旦執(zhí)行垃圾回收算法,其他 Javascript 腳本將被阻塞,需要等待垃圾回收完畢才能繼續(xù)執(zhí)行。這種行為叫做全停頓。

如上圖,過長(zhǎng)的全停頓將導(dǎo)致頁(yè)面卡頓。新生代因其空間小存活對(duì)象占用空間小,對(duì)全停頓影響不大,老生代的垃圾回收是造成全停頓的主因。為了降低老生代垃圾回收造成的卡頓,V8 將標(biāo)記過程分為一個(gè)個(gè)子標(biāo)記,讓子標(biāo)記和 Javascript 腳本交替進(jìn)行,這個(gè)解決方案叫做增量標(biāo)記算法。

以上就是一文詳解Javascript內(nèi)存機(jī)制與垃圾回收的詳細(xì)內(nèi)容,更多關(guān)于Javascript內(nèi)存機(jī)制與垃圾回收的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaScript?中如何攔截全局?Fetch?API?的請(qǐng)求和響應(yīng)問題

    JavaScript?中如何攔截全局?Fetch?API?的請(qǐng)求和響應(yīng)問題

    在本文中,我們介紹了什么是 JavaScript 攔截器,學(xué)習(xí)了如何通過給 Fetch API 使用猴子補(bǔ)丁和使用 fetch-intercept 庫(kù)來(lái)創(chuàng)建攔截器,對(duì)js攔截全局Fetch?API的請(qǐng)求和響應(yīng)知識(shí)感興趣的朋友跟隨小編一起看看吧
    2023-01-01
  • JavaScript將字符轉(zhuǎn)換為ASCII碼的實(shí)現(xiàn)方法

    JavaScript將字符轉(zhuǎn)換為ASCII碼的實(shí)現(xiàn)方法

    在Web前端開發(fā)中,字符編碼是處理文本數(shù)據(jù)時(shí)不可或缺的一部分,ASCII是一種廣泛使用的字符編碼標(biāo)準(zhǔn),它為每個(gè)字符分配了一個(gè)唯一的數(shù)字表示,解如何將字符轉(zhuǎn)換為ASCII碼,對(duì)于解析、生成和操作字符串具有重要意義,本文將詳細(xì)介紹這一過程,并提供多個(gè)實(shí)用的代碼示例
    2024-12-12
  • TypeScript中實(shí)現(xiàn)字符串格式化及數(shù)值對(duì)齊

    TypeScript中實(shí)現(xiàn)字符串格式化及數(shù)值對(duì)齊

    字符串格式化是處理文本展示的常見需求,尤其在需要規(guī)范數(shù)值、日期等數(shù)據(jù)的顯示格式時(shí)非常重要,TypeScript可以通過模板字符串、字符串方法和正則表達(dá)式組合實(shí)現(xiàn)類似功能,包括數(shù)值的左右對(duì)齊等場(chǎng)景,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2025-08-08
  • javascript二維數(shù)組轉(zhuǎn)置實(shí)例

    javascript二維數(shù)組轉(zhuǎn)置實(shí)例

    這篇文章主要介紹了javascript二維數(shù)組轉(zhuǎn)置方法,實(shí)例分析了數(shù)組行列交換的轉(zhuǎn)置技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-01-01
  • 微信小程序事件綁定傳參冒泡及捕獲的示例詳解

    微信小程序事件綁定傳參冒泡及捕獲的示例詳解

    這篇文章主要為大家介紹了微信小程序事件綁定傳參冒泡及捕獲的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • JS獲取一個(gè)未知DIV高度的方法

    JS獲取一個(gè)未知DIV高度的方法

    這篇文章主要介紹了JS獲取一個(gè)未知DIV高度的方法,涉及javascript針對(duì)頁(yè)面元素屬性的動(dòng)態(tài)操作相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-08-08
  • JavaScript常用數(shù)學(xué)函數(shù)用法示例

    JavaScript常用數(shù)學(xué)函數(shù)用法示例

    這篇文章主要介紹了JavaScript常用數(shù)學(xué)函數(shù)用法,結(jié)合實(shí)例形式分析了JavaScript常見的對(duì)數(shù)、平方、絕對(duì)值、正弦、四舍五入等相關(guān)數(shù)學(xué)函數(shù)使用技巧,需要的朋友可以參考下
    2018-05-05
  • 微信小程序在{{ }}中直接使用函數(shù)的方法示例

    微信小程序在{{ }}中直接使用函數(shù)的方法示例

    最近在學(xué)習(xí)微信小程序,在學(xué)習(xí)中遇到了一些問題,所以進(jìn)行了總結(jié)了下,這篇文章主要給大家介紹了關(guān)于微信小程序在{{ }}中直接使用函數(shù)的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • 第五篇Bootstrap 排版

    第五篇Bootstrap 排版

    使用bootstrap的排版特性可以創(chuàng)建標(biāo)題,段落,列表及其它內(nèi)聯(lián)元素。本文重點(diǎn)給大家介紹Bootstrap 排版 知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-06-06
  • js控制臺(tái)輸出的方法(詳解)

    js控制臺(tái)輸出的方法(詳解)

    下面小編就為大家?guī)?lái)一篇js控制臺(tái)輸出的方法(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2016-11-11

最新評(píng)論

昌江| 夏河县| 昌宁县| 左贡县| 垫江县| 克什克腾旗| 抚顺市| 儋州市| 醴陵市| 青州市| 武穴市| 双牌县| 伊宁市| 江津市| 全州县| 田林县| 勃利县| 永宁县| 锦州市| 甘孜| 益阳市| 淮滨县| 仙居县| 柯坪县| 南宫市| 新绛县| 德格县| 丰城市| 贡嘎县| 鄢陵县| 雷波县| 锡林浩特市| 微山县| 平邑县| 绥江县| 五台县| 鄄城县| 新沂市| 贺州市| 惠州市| 通化县|