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

一次徹底搞懂JavaScript中的引用賦值、淺拷貝和深拷貝

 更新時(shí)間:2025年12月26日 11:08:56   作者:2301_80853669  
在JavaScript編程中拷貝是一個(gè)常見(jiàn)的操作,而區(qū)分深拷貝和淺拷貝對(duì)于理解程序行為和預(yù)測(cè)程序結(jié)果至關(guān)重要,這篇文章主要介紹了JavaScript中引用賦值、淺拷貝和深拷貝的相關(guān)資料,需要的朋友可以參考下

前言

如果你經(jīng)常搞混 深淺拷貝 和 引用賦值,總是記不住它們有什么區(qū)別,在實(shí)際開(kāi)發(fā)中總是踩坑——比如不小心修改了原始數(shù)據(jù)、或者拷貝不徹底導(dǎo)致奇怪的 bug——那么恭喜你,這篇文章就是為你寫(xiě)的!我會(huì)用最直白的語(yǔ)言、清晰的圖示和大量實(shí)際代碼示例,幫你一次性徹底搞懂!在深入探討拷貝機(jī)制之前,我們需要先了解 JavaScript 的數(shù)據(jù)類型分類和內(nèi)存存儲(chǔ)機(jī)制的基礎(chǔ)概念

一、基礎(chǔ)概念鋪墊

1. JavaScript 數(shù)據(jù)類型分類

  • 基本數(shù)據(jù)類型:字符串(String)、數(shù)字(Number)、布爾(Boolean)、空(Null)、未定義(Undefined)、Symbol、BigInt。
  • 引用數(shù)據(jù)類型:對(duì)象(Object)、數(shù)組(Array)、函數(shù)(Function),還有兩個(gè)特殊的對(duì)象:正則(RegExp)、日期(Date)、正則表達(dá)式、Map、Set、和其他內(nèi)置對(duì)象(比如Promise、Error等)

2. 內(nèi)存存儲(chǔ)機(jī)制核心原理

JS 引擎將內(nèi)存劃分為棧內(nèi)存(Stack)堆內(nèi)存(Heap),不同類型的數(shù)據(jù)會(huì)被分配到不同的內(nèi)存區(qū)域:嵌套引用依舊遵循下列規(guī)則

特性棧內(nèi)存 (Stack)堆內(nèi)存 (Heap)
存儲(chǔ)內(nèi)容基本數(shù)據(jù)類型值、引用類型的指針引用數(shù)據(jù)類型的實(shí)際內(nèi)容
數(shù)據(jù)結(jié)構(gòu)后進(jìn)先出 (LIFO)動(dòng)態(tài)分配的樹(shù)/圖結(jié)構(gòu)
分配方式連續(xù)內(nèi)存,自動(dòng)分配隨機(jī)內(nèi)存,動(dòng)態(tài)分配
訪問(wèn)速度極快(直接CPU訪問(wèn))較慢(通過(guò)指針間接訪問(wèn))
大小限制?。ㄍǔ?-8MB)大(可達(dá)GB級(jí))
生命周期函數(shù)/塊作用域結(jié)束自動(dòng)釋放由垃圾回收器(GC)管理

如上圖所示,兩種數(shù)據(jù)類型的內(nèi)存訪問(wèn)流程如下所示

  • 基本數(shù)據(jù)類型的變量直接從棧內(nèi)存中獲取數(shù)據(jù)
  • 引用數(shù)據(jù)類型的變量訪問(wèn)過(guò)程:
    1. 讀取棧內(nèi)存中的指針(地址)
    2. 通過(guò)指針找到堆內(nèi)存中存儲(chǔ)的實(shí)際數(shù)據(jù)

二、不同類型的拷貝行為

1. 基本數(shù)據(jù)類型的拷貝

基本數(shù)據(jù)類型的拷貝非常簡(jiǎn)單,由于它們直接存儲(chǔ)在棧內(nèi)存中,拷貝時(shí)會(huì)直接復(fù)制值本身,不存在引用關(guān)系。

let a = 10;
let b = a; // 直接復(fù)制值
b = 20;
console.log(a); // 10(不受 b 修改影響)
console.log(b); // 20

2. 引用數(shù)據(jù)類型的拷貝

方式一:引用賦值(非拷貝)

引用數(shù)據(jù)類型在賦值時(shí),默認(rèn)是引用賦值(即復(fù)制指針地址),而非復(fù)制實(shí)際內(nèi)容。這意味著兩個(gè)變量會(huì)指向堆內(nèi)存中的同一個(gè)對(duì)象。修改其中一個(gè)另一個(gè)會(huì)受影響。

let a = [1, 2, 5];
let b = a; // 引用賦值(復(fù)制指針)
a[1] = 4; // 修改 a 指向的數(shù)組
console.log(a); // [1, 4, 5]
console.log(b); // [1, 4, 5](b 也受影響)
console.log(a === b); // true(指向同一個(gè)對(duì)象)

方式二: 淺拷貝

淺拷貝是針對(duì)引用類型的拷貝方式,它會(huì)創(chuàng)建一個(gè)新對(duì)象,但只復(fù)制對(duì)象的第一層屬性。其規(guī)則是:

  • 對(duì)基本類型屬性:直接復(fù)制值
  • 對(duì)引用類型屬性:僅復(fù)制指針(不復(fù)制指向的對(duì)象本身)

示例1:對(duì)數(shù)組 a = [1, 2, [3, 4], 5] 進(jìn)行淺拷貝得到 b 后:

  • b[0]b[1]、b[3] 是基本類型,修改它們不會(huì)影響 a
  • b[2] 是引用類型(數(shù)組),修改 b[2] 會(huì)同時(shí)影響 a[2],因?yàn)樗鼈冎赶蛲粋€(gè)子數(shù)組
const a = [1, 2, [3, 4], 5];
const b = [...a]; // 淺拷貝

a[0] = 100;
console.log(b[0]); // 1(不受影響,基本類型獨(dú)立)

a[2][1] = 400; // 修改子數(shù)組元素
console.log(b[2][1]); // 400(受影響,共享子數(shù)組引用)

示例2:

// 原始對(duì)象
const a = {
  name: "alice",  // 基本類型(棧內(nèi)存存儲(chǔ)值)
  profile: {      // 引用類型(堆內(nèi)存存儲(chǔ)對(duì)象,棧內(nèi)存存儲(chǔ)指針)
    age: 25,
    city: "beijing"
  }
};

// 使用擴(kuò)展運(yùn)算符進(jìn)行淺拷貝
const b = { ...a };

// 修改淺拷貝對(duì)象
b.name = "bob";
b.profile.age = 30;
b.profile.city = "shanghai";

// 查看結(jié)果
console.log("原始對(duì)象 a.name:", a.name); 
// 輸出:"alice"(基本類型值獨(dú)立,不受影響)

console.log("原始對(duì)象 a.profile.age:", a.profile.age); 
// 輸出:30(引用類型共享堆內(nèi)存,被修改)

console.log("原始對(duì)象 a.profile.city:", a.profile.city); 
// 輸出:"shanghai"(引用類型共享堆內(nèi)存,被修改)

console.log("a.profile === b.profile:", a.profile === b.profile); 
// 輸出:true(兩者指向堆中同一個(gè)對(duì)象)

常見(jiàn)的淺拷貝方法

  1. 擴(kuò)展運(yùn)算符(推薦)
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
  1. Object.assign()
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, obj);
  1. 數(shù)組的 slice()、concat() 方法
const arr = [1, 2, { a: 3 }];
const shallowCopy1 = arr.slice();
const shallowCopy2 = [].concat(arr);
  1. Array.from()
const arr = [1, 2, { a: 3 }];
const shallowCopy = Array.from(arr);

方式三、深拷貝

深拷貝會(huì)創(chuàng)建一個(gè)全新的對(duì)象,完全復(fù)制原始對(duì)象的所有層級(jí)屬性,包括嵌套的引用類型,使得新舊對(duì)象完全獨(dú)立。

實(shí)現(xiàn)方式 1:JSON 方法(最常用但有局限)

// 原始對(duì)象
const a = {
  name: "alice",  // 基本類型(棧內(nèi)存存儲(chǔ)值)
  profile: {      // 引用類型(堆內(nèi)存存儲(chǔ)對(duì)象)
    age: 25,
    city: "beijing"
  }
};

// 實(shí)現(xiàn)深拷貝
const deepCopy = JSON.parse(JSON.stringify(a));

// 修改深拷貝對(duì)象的屬性
deepCopy.name = "bob"; // 修改基本類型
deepCopy.profile.age = 30; // 修改嵌套引用類型
deepCopy.profile.city = "shanghai";

// 查看結(jié)果對(duì)比
console.log("原始對(duì)象 a.name:", a.name); 
// 輸出:"alice"(基本類型不受影響)

console.log("原始對(duì)象 a.profile.age:", a.profile.age); 
// 輸出:25(嵌套引用類型也不受影響)

console.log("原始對(duì)象 a.profile.city:", a.profile.city); 
// 輸出:"beijing"(嵌套引用類型完全獨(dú)立)

console.log("a.profile === deepCopy.profile:", a.profile === deepCopy.profile); 
// 輸出:false(兩者指向堆中不同對(duì)象)

注意限制:

  • 無(wú)法復(fù)制函數(shù)、undefined、Symbol
  • 日期對(duì)象會(huì)被轉(zhuǎn)換為字符串
  • 無(wú)法處理循環(huán)引用
  • 會(huì)丟失原型鏈信息

實(shí)現(xiàn)方式 2:遞歸實(shí)現(xiàn)(自定義深拷貝函數(shù))

由于遞歸實(shí)現(xiàn)較為復(fù)雜,這里不展開(kāi)詳細(xì)代碼,但基本原理是遍歷對(duì)象的所有屬性,對(duì)引用類型屬性遞歸調(diào)用拷貝函數(shù),直到所有層級(jí)都被復(fù)制。

三、深淺拷貝對(duì)比總結(jié)

類型引用類型內(nèi)存地址第一層修改第二層修改
引用賦值引用復(fù)制相同相互影響相互影響
淺拷貝僅第一層值復(fù)制,嵌套層引用復(fù)制不同獨(dú)立相互影響
深拷貝完全復(fù)制不同獨(dú)立獨(dú)立

深淺拷貝的核心區(qū)別在于對(duì)嵌套引用類型的處理方式,這直接決定了拷貝后對(duì)象的獨(dú)立性:

  • 引用賦值:本質(zhì)上不是拷貝,只是復(fù)制了對(duì)象的引用指針。兩個(gè)變量共享同一塊堆內(nèi)存,任何層級(jí)的修改都會(huì)相互影響,內(nèi)存地址相同。
  • 淺拷貝:創(chuàng)建新的內(nèi)存地址存儲(chǔ)對(duì)象,但僅對(duì)第一層屬性進(jìn)行值復(fù)制。對(duì)于基本類型屬性,修改后彼此獨(dú)立;但對(duì)于嵌套的引用類型屬性,仍共享原始引用,修改會(huì)相互影響。
  • 深拷貝:完全創(chuàng)建新的對(duì)象,遞歸復(fù)制所有層級(jí)的屬性(包括嵌套引用類型)。新舊對(duì)象擁有完全獨(dú)立的內(nèi)存空間,任何層級(jí)的修改都不會(huì)相互影響,內(nèi)存地址不同。

到此這篇關(guān)于JavaScript中引用賦值、淺拷貝和深拷貝的文章就介紹到這了,更多相關(guān)JS引用賦值、淺拷貝和深拷貝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • js實(shí)現(xiàn)加載頁(yè)面就自動(dòng)觸發(fā)超鏈接的示例

    js實(shí)現(xiàn)加載頁(yè)面就自動(dòng)觸發(fā)超鏈接的示例

    下面小編就為大家?guī)?lái)一篇js實(shí)現(xiàn)加載頁(yè)面就自動(dòng)觸發(fā)超鏈接的示例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • js實(shí)現(xiàn)帶緩沖效果的仿QQ面板折疊菜單代碼

    js實(shí)現(xiàn)帶緩沖效果的仿QQ面板折疊菜單代碼

    這篇文章主要介紹了js實(shí)現(xiàn)帶緩沖效果的仿QQ面板折疊菜單代碼,通過(guò)JavaScript定時(shí)函數(shù)遞歸調(diào)用實(shí)現(xiàn)折疊菜單的緩沖效果,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • 原生js實(shí)現(xiàn)隨機(jī)點(diǎn)名功能

    原生js實(shí)現(xiàn)隨機(jī)點(diǎn)名功能

    這篇文章主要為大家詳細(xì)介紹了原生js實(shí)現(xiàn)隨機(jī)點(diǎn)名功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • 微信小程序—setTimeOut定時(shí)器的問(wèn)題及解決

    微信小程序—setTimeOut定時(shí)器的問(wèn)題及解決

    這篇文章主要介紹了微信小程序—setTimeOut定時(shí)器的問(wèn)題及解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • JavaScript彈出框與事件綁定的超詳細(xì)解析

    JavaScript彈出框與事件綁定的超詳細(xì)解析

    這篇文章主要介紹了JavaScript彈出框與事件綁定的相關(guān)資料,通過(guò)示例講解了實(shí)現(xiàn)方式、綜合應(yīng)用及最佳實(shí)踐,如避免內(nèi)存泄漏、優(yōu)化性能、提升用戶體驗(yàn)與可訪問(wèn)性,需要的朋友可以參考下
    2025-05-05
  • JS實(shí)現(xiàn)仿PS的調(diào)色板效果完整實(shí)例

    JS實(shí)現(xiàn)仿PS的調(diào)色板效果完整實(shí)例

    這篇文章主要介紹了JS實(shí)現(xiàn)仿PS的調(diào)色板效果,結(jié)合完整實(shí)例形式分析了javascript通過(guò)運(yùn)算與動(dòng)態(tài)操作頁(yè)面元素實(shí)現(xiàn)調(diào)色板功能的相關(guān)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-12-12
  • js調(diào)用css屬性寫(xiě)法

    js調(diào)用css屬性寫(xiě)法

    對(duì)于沒(méi)有中劃線的css屬性一般直接使用style.屬性名即可,對(duì)于含有中劃線的css屬性,將每個(gè)中劃線去掉并將每個(gè)中劃線后的第一個(gè)字符換成大寫(xiě)即可,感興趣的朋友可以參考下
    2013-09-09
  • JavaScript中內(nèi)存泄漏的介紹與教程(推薦)

    JavaScript中內(nèi)存泄漏的介紹與教程(推薦)

    內(nèi)存泄露是指一塊被分配的內(nèi)存既不能使用,又不能回收,直到瀏覽器進(jìn)程結(jié)束。下面這篇文章主要給的大家介紹了關(guān)于JavaScript中內(nèi)存泄漏的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-06-06
  • JavaScript實(shí)現(xiàn)鼠標(biāo)經(jīng)過(guò)表格某行時(shí)此行變色

    JavaScript實(shí)現(xiàn)鼠標(biāo)經(jīng)過(guò)表格某行時(shí)此行變色

    這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)鼠標(biāo)經(jīng)過(guò)表格某行時(shí)此行變色,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • 使用js的replace()方法查找字符示例代碼

    使用js的replace()方法查找字符示例代碼

    JavaScript具有一個(gè)非常有用的方法replace(),可以用它利用備選字符集途歡指定的字符,下面有個(gè)不錯(cuò)的示例,大家可以嘗試操作下
    2013-10-10

最新評(píng)論

军事| 渭源县| 铜陵市| 凯里市| 延庆县| 荣成市| 濮阳市| 襄城县| 闵行区| 灵石县| 师宗县| 昌宁县| 舞阳县| 容城县| 迁安市| 固原市| 曲阜市| 嘉鱼县| 定南县| 江源县| 西宁市| 东兴市| 凤凰县| 新疆| 中江县| 化德县| 右玉县| 子洲县| 永年县| 全州县| 中西区| 青阳县| 吴堡县| 阿拉善左旗| 巴南区| 亳州市| 宣恩县| 察隅县| 南安市| 壤塘县| 周至县|