最新国产好看的视频,伊人天堂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ī)制,通過代碼實(shí)戰(zhàn)演示了基本類型和引用類型的數(shù)據(jù)存儲(chǔ)方式,并解釋了閉包和內(nèi)存泄漏的概念,總結(jié)了棧和堆的區(qū)別,提供了面試高頻問題的回答方法,需要的朋友可以參考下

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

1. 核心比喻:辦公桌 vs 倉庫

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

棧(Stack) = 員工的辦公桌

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

堆(Heap) = 公司的公共倉庫

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

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

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

  • 基本數(shù)據(jù)類型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)化),但邏輯上我們將其視為值類型。

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

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

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

工作機(jī)制

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

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

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

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

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é)論:基本類型是值拷貝?;ゲ挥绊?。

場(chǎng)景二:引用類型(棧存地址,堆存數(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é)論:引用類型是引用拷貝(淺拷貝)。obj1obj2 指向堆中的同一個(gè)對(duì)象。修改其中一個(gè),另一個(gè)也會(huì)變。

5. 垃圾回收:誰在打掃戰(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ā),遍歷所有能訪問到的對(duì)象,打上“存活”標(biāo)記。
  2. 清除:遍歷堆內(nèi)存,那些沒有被打上標(biāo)記的對(duì)象,說明已經(jīng)沒有任何變量引用它們了,于是被判定為“垃圾”,占用內(nèi)存被釋放。

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

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

常見泄漏場(chǎng)景

// 1. 意外全局變量
function leak() {
  leakedVar = "I am global now"; // 忘記寫 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)容基本類型、執(zhí)行上下文引用類型(對(duì)象、數(shù)組等)
大小小,固定大小大,動(dòng)態(tài)分配
存取速度
管理方式自動(dòng)分配與釋放(LIFO)垃圾回收機(jī)制(GC)
數(shù)據(jù)結(jié)構(gòu)線性,有序非線性,無序
拷貝行為值拷貝(深拷貝效果)引用拷貝(淺拷貝)

面試高頻問答

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

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

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

A: 深拷貝是在堆中開辟一塊新內(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ì)阻止外部變量被回收,這是正常現(xiàn)象。但如果閉包長期存在且引用了巨大的無用數(shù)據(jù),且無法被 GC 回收,才會(huì)導(dǎo)致泄漏。

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

  • 頁面按鈕禁用與解除禁用的方法

    頁面按鈕禁用與解除禁用的方法

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

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

    這篇文章主要介紹了ES6中new Function()語法及應(yīng)用,結(jié)合實(shí)例形式分析了ES6中new Function()的基本語法、功能、原理、閉包等相關(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開發(fā)跨域原因的多種解決方案

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

    我們?cè)趙eb項(xiàng)目開發(fā)中,經(jīng)常會(huì)遇到各種跨域的問題,本文帶你解決web開發(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)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起看看吧。
    2017-12-12
  • javascript封裝 Cookie 應(yīng)用接口

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

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

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

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

    JavaScript數(shù)組filter方法

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

最新評(píng)論

安义县| 微山县| 津市市| 鹿泉市| 正阳县| 洱源县| 辽阳县| 舟山市| 镇宁| 莒南县| 芒康县| 岐山县| 石狮市| 德阳市| 噶尔县| 志丹县| 剑河县| 河源市| 伊通| 绵阳市| 石狮市| 漳州市| 屏东县| 东兰县| 龙游县| 电白县| 安化县| 体育| 特克斯县| 娱乐| 武胜县| 房产| 桐乡市| 淮阳县| 绥化市| 平远县| 武威市| 衢州市| 舞钢市| 峡江县| 竹山县|