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

JavaScript內(nèi)存機(jī)制之堆內(nèi)存(Heap)與棧內(nèi)存(Stack)詳解

 更新時(shí)間:2026年05月08日 09:35:16   作者:yqcoder  
文章將JavaScript引擎中的內(nèi)存分為棧和堆,詳細(xì)描述了它們的特點(diǎn)、用途、管理方式和垃圾回收機(jī)制,通過(guò)代碼實(shí)戰(zhàn)演示了基本類(lèi)型和引用類(lèi)型的數(shù)據(jù)存儲(chǔ)方式,并解釋了閉包和內(nèi)存泄漏的概念,總結(jié)了棧和堆的區(qū)別,提供了面試高頻問(wèn)題的回答方法,需要的朋友可以參考下

在 JavaScript 引擎(如 V8)中,內(nèi)存主要分為兩個(gè)區(qū)域:棧內(nèi)存(Stack)堆內(nèi)存(Heap)
它們就像公司的辦公桌倉(cāng)庫(kù),分工明確,協(xié)作高效。

1. 核心比喻:辦公桌 vs 倉(cāng)庫(kù)

為了通俗易懂,我們把瀏覽器內(nèi)存想象成一家公司:

棧(Stack) = 員工的辦公桌

  • 特點(diǎn):空間小,但就在手邊,存取速度極快。
  • 用途:存放正在處理的臨時(shí)數(shù)據(jù)(如函數(shù)調(diào)用、局部變量)。
  • 管理:老板(JS 引擎)嚴(yán)格管理。你離開(kāi)座位(函數(shù)執(zhí)行結(jié)束),桌子上的東西立刻被清空。
  • 結(jié)構(gòu):先進(jìn)后出(LIFO),像疊盤(pán)子一樣。

堆(Heap) = 公司的公共倉(cāng)庫(kù)

  • 特點(diǎn):空間巨大,但距離遠(yuǎn),存取速度相對(duì)較慢。
  • 用途:存放大件物品、復(fù)雜對(duì)象(如大數(shù)組、復(fù)雜對(duì)象、閉包)。
  • 管理:比較松散。東西扔進(jìn)去就不管了,直到倉(cāng)庫(kù)滿(mǎn)了,清潔工(垃圾回收器 GC)才會(huì)來(lái)清理沒(méi)人用的東西。
  • 結(jié)構(gòu):無(wú)序,像一個(gè)巨大的雜物間,需要通過(guò)“地址標(biāo)簽”才能找到東西。

2. 棧(Stack):快速、有序、自動(dòng)清理

存儲(chǔ)內(nèi)容

  • 基本數(shù)據(jù)類(lèi)型Number, String, Boolean, Null, Undefined, Symbol, BigInt。
  • 執(zhí)行上下文:函數(shù)調(diào)用棧(Call Stack),記錄當(dāng)前執(zhí)行到哪里了。

工作機(jī)制

  1. 分配:當(dāng)聲明一個(gè)變量或調(diào)用一個(gè)函數(shù)時(shí),內(nèi)存會(huì)自動(dòng)在棧頂分配一塊固定大小的空間。
  2. 釋放:當(dāng)函數(shù)執(zhí)行完畢或變量超出作用域時(shí),這塊內(nèi)存會(huì)自動(dòng)彈出并釋放。
  3. 速度:極快,因?yàn)椴恍枰檎遥苯硬僮鳁m斨羔槨?/li>

注意:在 JS 中,短字符串有時(shí)也會(huì)存儲(chǔ)在棧中(取決于引擎優(yōu)化),但邏輯上我們將其視為值類(lèi)型。

3. 堆(Heap):龐大、無(wú)序、手動(dòng)回收

存儲(chǔ)內(nèi)容

  • 引用數(shù)據(jù)類(lèi)型Object, Array, Function, Date, RegExp 等。
  • 大型數(shù)據(jù):無(wú)論數(shù)據(jù)多大,都存放在堆中。

工作機(jī)制

  1. 分配:當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí),引擎會(huì)在堆中開(kāi)辟一塊空間存放數(shù)據(jù)。
  2. 引用:棧中只存儲(chǔ)一個(gè)指針(內(nèi)存地址),指向堆中的這塊數(shù)據(jù)。
  3. 釋放不會(huì)自動(dòng)立即釋放。需要依靠瀏覽器的垃圾回收機(jī)制(Garbage Collection, GC) 來(lái)定期掃描,找出不再被引用的對(duì)象并清除。

4. 代碼實(shí)戰(zhàn):數(shù)據(jù)是如何存儲(chǔ)的?

讓我們通過(guò)代碼看看棧和堆是如何協(xié)作的。

場(chǎng)景一:基本類(lèi)型(全在棧中)

let a = 10;
let b = a; // 拷貝值
b = 20;

console.log(a); // 10
console.log(b); // 20

內(nèi)存圖解

Stack (棧)
+-------+
| b: 20 |  <-- 修改 b,不影響 a
+-------+
| a: 10 |  <-- a 保持原值
+-------+

結(jié)論:基本類(lèi)型是值拷貝?;ゲ挥绊?。

場(chǎng)景二:引用類(lèi)型(棧存地址,堆存數(shù)據(jù))

let obj1 = { name: "Lingma" };
let obj2 = obj1; // 拷貝地址(指針)
obj2.name = "Aliyun";

console.log(obj1.name); // "Aliyun" ?? obj1 也被改變了!
console.log(obj2.name); // "Aliyun"

內(nèi)存圖解

Stack (棧)                  Heap (堆)
+----------+              +------------------+
| obj1     |------------->| { name: "Aliyun" } |
+----------+              +------------------+
| obj2     |-------------^  (同一個(gè)對(duì)象)
+----------+

結(jié)論:引用類(lèi)型是引用拷貝(淺拷貝)。obj1obj2 指向堆中的同一個(gè)對(duì)象。修改其中一個(gè),另一個(gè)也會(huì)變。

5. 垃圾回收:誰(shuí)在打掃戰(zhàn)場(chǎng)?

既然堆內(nèi)存不會(huì)自動(dòng)釋放,那什么時(shí)候清理呢?
瀏覽器使用 垃圾回收機(jī)制(GC)。主流算法是 標(biāo)記-清除(Mark-and-Sweep)。

工作流程

  1. 標(biāo)記:GC 從根節(jié)點(diǎn)(如 window、全局變量)出發(fā),遍歷所有能訪(fǎng)問(wèn)到的對(duì)象,打上“存活”標(biāo)記。
  2. 清除:遍歷堆內(nèi)存,那些沒(méi)有被打上標(biāo)記的對(duì)象,說(shuō)明已經(jīng)沒(méi)有任何變量引用它們了,于是被判定為“垃圾”,占用內(nèi)存被釋放。

內(nèi)存泄漏(Memory Leak)

如果代碼中存在意外的全局變量、未清理的定時(shí)器循環(huán)引用,導(dǎo)致某些對(duì)象永遠(yuǎn)無(wú)法被 GC 標(biāo)記為“可回收”,內(nèi)存就會(huì)越占越多,最終導(dǎo)致頁(yè)面卡頓甚至崩潰。

常見(jiàn)泄漏場(chǎng)景

// 1. 意外全局變量
function leak() {
  leakedVar = "I am global now"; // 忘記寫(xiě) let/var/const
}

// 2. 未清除的定時(shí)器
const timer = setInterval(() => {
  console.log("I never stop");
}, 1000);
// 如果不清除 clearInterval(timer),回調(diào)函數(shù)及其引用的變量永遠(yuǎn)不會(huì)被回收

6. 總結(jié)與面試考點(diǎn)

特性棧(Stack)堆(Heap)
存儲(chǔ)內(nèi)容基本類(lèi)型、執(zhí)行上下文引用類(lèi)型(對(duì)象、數(shù)組等)
大小小,固定大小大,動(dòng)態(tài)分配
存取速度
管理方式自動(dòng)分配與釋放(LIFO)垃圾回收機(jī)制(GC)
數(shù)據(jù)結(jié)構(gòu)線(xiàn)性,有序非線(xiàn)性,無(wú)序
拷貝行為值拷貝(深拷貝效果)引用拷貝(淺拷貝)

面試高頻問(wèn)答

Q1: 為什么基本類(lèi)型賦值互不影響,而對(duì)象賦值會(huì)相互影響?

A: 因?yàn)榛绢?lèi)型存在棧中,賦值是復(fù)制值;對(duì)象存在堆中,棧里只存地址,賦值是復(fù)制地址,兩者指向同一塊堆內(nèi)存。

Q2: 什么是深拷貝?如何實(shí)現(xiàn)?

A: 深拷貝是在堆中開(kāi)辟一塊新內(nèi)存,將原對(duì)象的所有層級(jí)數(shù)據(jù)完整復(fù)制一份。實(shí)現(xiàn)方式:JSON.parse(JSON.stringify(obj))(有局限)、遞歸復(fù)制、或使用 structuredClone API。

Q3: 閉包會(huì)導(dǎo)致內(nèi)存泄漏嗎?

A: 不一定。閉包會(huì)阻止外部變量被回收,這是正?,F(xiàn)象。但如果閉包長(zhǎng)期存在且引用了巨大的無(wú)用數(shù)據(jù),且無(wú)法被 GC 回收,才會(huì)導(dǎo)致泄漏。

博主寄語(yǔ)
理解堆和棧,不僅僅是為了應(yīng)付面試。
當(dāng)你遇到“修改了一個(gè)對(duì)象,另一個(gè)莫名其妙也變了”的 Bug 時(shí),你會(huì)想起堆內(nèi)存的共享特性。
當(dāng)你發(fā)現(xiàn)頁(yè)面越來(lái)越卡時(shí),你會(huì)想起堆內(nèi)存的垃圾回收。

記住口訣
棧小快,存基本,自動(dòng)清理不費(fèi)力。
堆大慢,存對(duì)象,引用拷貝要注意。
垃圾回收靠標(biāo)記,內(nèi)存泄漏要警惕。

以上就是JavaScript內(nèi)存之堆內(nèi)存(Heap)與棧內(nèi)存(Stack)詳解的詳細(xì)內(nèi)容,更多關(guān)于JavaScript堆內(nèi)存(Heap)與棧內(nèi)存(Stack)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 頁(yè)面按鈕禁用與解除禁用的方法

    頁(yè)面按鈕禁用與解除禁用的方法

    這篇文章主要介紹了頁(yè)面按鈕禁用與解除禁用的方法,需要的朋友可以參考下
    2014-02-02
  • ES6中new Function()語(yǔ)法及應(yīng)用實(shí)例分析

    ES6中new Function()語(yǔ)法及應(yīng)用實(shí)例分析

    這篇文章主要介紹了ES6中new Function()語(yǔ)法及應(yīng)用,結(jié)合實(shí)例形式分析了ES6中new Function()的基本語(yǔ)法、功能、原理、閉包等相關(guān)使用技巧,需要的朋友可以參考下
    2020-02-02
  • JavaScript數(shù)據(jù)結(jié)構(gòu)之雙向鏈表

    JavaScript數(shù)據(jù)結(jié)構(gòu)之雙向鏈表

    這篇文章主要為大家詳細(xì)介紹了JavaScript數(shù)據(jù)結(jié)構(gòu)之雙向鏈表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • web開(kāi)發(fā)跨域原因的多種解決方案

    web開(kāi)發(fā)跨域原因的多種解決方案

    我們?cè)趙eb項(xiàng)目開(kāi)發(fā)中,經(jīng)常會(huì)遇到各種跨域的問(wèn)題,本文帶你解決web開(kāi)發(fā)中多種跨域原因的解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-09-09
  • js實(shí)現(xiàn)簡(jiǎn)單放大鏡特效

    js實(shí)現(xiàn)簡(jiǎn)單放大鏡特效

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)簡(jiǎn)單放大鏡特效,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • javascript 判斷數(shù)組是否已包含了某個(gè)元素的函數(shù)

    javascript 判斷數(shù)組是否已包含了某個(gè)元素的函數(shù)

    javascript判斷數(shù)組是否已包含了某個(gè)元素的js函數(shù),方便數(shù)組的判斷。
    2010-05-05
  • 利用10行js代碼實(shí)現(xiàn)上下滾動(dòng)公告效果

    利用10行js代碼實(shí)現(xiàn)上下滾動(dòng)公告效果

    這篇文章主要給大家介紹了關(guān)于利用10行js代碼實(shí)現(xiàn)滾動(dòng)公告效果的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧。
    2017-12-12
  • javascript封裝 Cookie 應(yīng)用接口

    javascript封裝 Cookie 應(yīng)用接口

    本文通過(guò)幾個(gè)簡(jiǎn)單的示例向大家展示了javascript封裝cookie的注意事項(xiàng)及操作方法,非常的簡(jiǎn)單實(shí)用,最后附上一則具體實(shí)例,有需要的小火把可以參考下。
    2015-08-08
  • js禁止小鍵盤(pán)輸入數(shù)字功能代碼

    js禁止小鍵盤(pán)輸入數(shù)字功能代碼

    js禁止小鍵盤(pán)輸入數(shù)字功能代碼,需要的朋友可以參考下。
    2011-08-08
  • JavaScript數(shù)組filter方法

    JavaScript數(shù)組filter方法

    filter()創(chuàng)建一個(gè)新的數(shù)組,新數(shù)組中的元素是通過(guò)檢查指定數(shù)組中符合條件的所有元素,這篇文章主要介紹了JavaScript數(shù)組filter方法,需要的朋友可以參考下
    2022-12-12

最新評(píng)論

石城县| 纳雍县| 科技| 桓台县| 威远县| 老河口市| 阿坝| 五原县| 彰武县| 通化市| 鸡泽县| 花莲县| 石阡县| 常宁市| 兖州市| 青田县| 若羌县| 仁化县| 鄂托克前旗| 伊金霍洛旗| 苍山县| 繁昌县| 苏尼特左旗| 根河市| 巫溪县| 射阳县| 嘉黎县| 讷河市| 泸定县| 东光县| 德庆县| 铜鼓县| 金阳县| 宁河县| 烟台市| 平乐县| 公主岭市| 大渡口区| 福鼎市| 泾阳县| 平谷区|