JavaScript 深淺拷貝全面解析

在 JavaScript 中,深淺拷貝是處理對象復制的重要概念。它們的核心區別在于對 引用類型數據 的處理方式,理解這一點對避免程序中的意外數據污染至關重要。


一、核心概念解析

1. 基本類型 vs 引用類型
  • 基本類型Number, String, Boolean, null, undefined, Symbol, BigInt
    直接存儲在棧內存中,復制時創建獨立副本。

  • 引用類型Object, Array, Function, Date, RegExp
    棧內存存儲指針,堆內存存儲實際數據,復制時默認只復制指針。

2. 賦值 vs 淺拷貝 vs 深拷貝
操作類型特點是否共享引用
直接賦值復制指針,完全共享數據?
淺拷貝創建新對象,但嵌套引用類型仍共享嵌套層級共享 ?
深拷貝完全獨立的新對象,所有層級不共享?

二、淺拷貝實現方案

1. 手動實現
function shallowCopy(obj) {if (typeof obj !== 'object' || obj === null) return obj;const newObj = Array.isArray(obj) ? [] : {};for (let key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] = obj[key]; // 僅復制第一層}}return newObj;
}
2. 內置方法
  • Object.assign()

    const obj = { a: 1, b: { c: 2 } };
    const copy = Object.assign({}, obj);
    
  • 展開運算符 ...

    const arr = [1, { x: 2 }];
    const arrCopy = [...arr];
    
3. 特性驗證
const original = { a: 1, b: { c: 2 } };
const copy = shallowCopy(original);copy.b.c = 999; // 修改嵌套對象
console.log(original.b.c); // 999 → 數據被污染

三、深拷貝實現方案

1. JSON 序列化法
const deepCopyJSON = obj => JSON.parse(JSON.stringify(obj));

局限性

  • 無法處理 undefinedSymbol、函數
  • 忽略原型鏈
  • 不能解決循環引用
  • 會破壞特殊對象(如 Date 變為字符串)
2. 遞歸實現(基礎版)
function deepClone(source) {if (source === null || typeof source !== 'object') return source;const target = Array.isArray(source) ? [] : {};for (let key in source) {if (source.hasOwnProperty(key)) {target[key] = deepClone(source[key]); // 遞歸復制}}return target;
}
3. 增強版深拷貝

處理復雜場景:

function enhancedDeepClone(source, map = new WeakMap()) {// 處理循環引用if (map.has(source)) return map.get(source);// 處理特殊對象if (source instanceof Date) return new Date(source);if (source instanceof RegExp) return new RegExp(source);const target = Array.isArray(source) ? [] : {};map.set(source, target);// 處理Symbol作為keyconst symKeys = Object.getOwnPropertySymbols(source);symKeys.forEach(symKey => {target[symKey] = enhancedDeepClone(source[symKey], map);});for (let key in source) {if (source.hasOwnProperty(key)) {target[key] = enhancedDeepClone(source[key], map);}}return target;
}
4. 第三方庫
  • lodash 的 _.cloneDeep()
    import _ from 'lodash';
    const perfectCopy = _.cloneDeep(original);
    

四、性能與選擇策略

方法優點缺點適用場景
淺拷貝速度快、內存占用少嵌套數據不安全簡單對象結構
JSON法簡單快捷丟失特殊類型無特殊類型的數據
遞歸深拷貝完全控制性能消耗大復雜對象結構
第三方庫功能完善增加依賴生產環境推薦

五、應用場景示例

  1. 狀態管理
    Redux 的 reducer 中必須使用深拷貝保證狀態不可變性:

    function reducer(state, action) {return {...state,user: _.cloneDeep(action.payload) // 確保狀態獨立};
    }
    
  2. 數據快照
    保存歷史記錄時需完全獨立的數據副本:

    const gameState = { players: [{ score: 0 }], level: 1 };
    const history = [deepClone(gameState)];
    
  3. 配置對象復用
    修改配置模板不影響原始模板:

    const defaultConfig = { theme: 'dark', permissions: { read: true } };
    const userConfig = deepClone(defaultConfig);
    userConfig.permissions.write = false;
    

六、常見誤區

  1. 誤以為 Object.assign() 是深拷貝
    實際上它只能實現第一層深拷貝,嵌套對象仍是淺拷貝。

  2. 忽略循環引用問題

    const obj = { a: 1 };
    obj.self = obj;
    deepClone(obj); // 基礎實現會棧溢出
    
  3. 處理特殊對象不當
    直接克隆 Date 對象會丟失方法:

    const date = new Date();
    const badCopy = JSON.parse(JSON.stringify(date)); // 變成字符串
    

掌握深淺拷貝的底層原理和實現方式,能幫助開發者根據實際需求選擇最優解決方案,在保證數據安全性的同時平衡性能消耗。對于日常開發,推薦優先使用成熟的工具庫(如 lodash),但在需要精細控制時,理解手寫實現原理至關重要。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/71995.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/71995.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/71995.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【大模型】大模型推理能力深度剖析:從通用模型到專業優化

大模型推理能力深度剖析:從通用模型到專業優化 大模型推理能力深度剖析:從通用模型到專業優化一、通用語言模型與推理模型的區別(一)通用語言模型:多任務的“萬金油”(二)推理模型:復…

RISC-V架構的平臺級中斷控制器(PLIC:platform-level interrupt controller)詳解

英文縮寫 英文縮寫中文含義PLICplatform-level interrupt controller,平臺級中斷控制器SMTsimultaneous multi-threading,并發多線程HARTRISC-V架構中的硬件線程SMTsimultaneous multi-threading,多線程執行M-MODEmachine mode,機…

[Web 安全] PHP 反序列化漏洞 —— PHP 序列化 反序列化

關注這個專欄的其他相關筆記:[Web 安全] 反序列化漏洞 - 學習筆記-CSDN博客 0x01:PHP 序列化 — Serialize 序列化就是將對象的狀態信息轉化為可以存儲或傳輸的形式的過程,在 PHP 中,通常使用 serialize() 函數來完成序列化的操作…

航空裝配自動化神器Ethercat轉profient網關搭配機器人精準控制

生產管理系統通過網關與裝配機器人連接,加快航空器機身的裝配速度,減少人為誤差。 航空制造對裝配線的精度和效率有著極高的要求。某航空制造廠使用的耐達訊Profinet轉EtherCAT協議網關NY-PN-ECATM,將其生產管理系統與裝配機器人連接&#xf…

什么是MySql的主從復制(主從同步)?

主頁還有其他面試題總結,有需要的可以去看一下,喜歡的就留個三連再走吧~ 1.什么是MySql的主從復制原理? 主從復制的核心就是二進制binlog(DDL(數據定義語言)語句和DML(數據操縱語言&#xff09…

自然語言處理:初識自然語言處理

介紹 大家好,博主又來給大家分享知識了。從這次開始,博主給大家分享自然語言處理這個領域的內容。這也是博主非常感興趣的研究領域。 最開始,博主計劃在自然語言處理系列的第一篇博文中,和大家聊聊文本規范化這個話題。畢竟在自…

【保姆級視頻教程(二)】YOLOv12訓練數據集構建:標簽格式轉換-劃分-YAML 配置 避坑指南 | 小白也能輕松玩轉目標檢測!

【2025全站首發】YOLOv12訓練數據集構建:標簽格式轉換-劃分-YAML 配置 避坑指南 | 小白也能輕松玩轉目標檢測! 文章目錄 1. 數據集準備1.1 標簽格式轉換1.2 數據集劃分1.3 yaml配置文件創建 2. 訓練驗證 1. 數據集準備 示例數據集下載鏈接:P…

【人工智能】藍耘智算平臺盛大發布DeepSeek滿血版:開創AI推理體驗新紀元

📝個人主頁🌹:Eternity._ 🌹🌹期待您的關注 🌹🌹 ? 藍耘智算平臺 藍耘智算平臺核心技術與突破元生代推理引擎快速入門:三步調用大模型接口,OpenAI SDK無縫兼容實戰用例文…

【網絡編程】幾個常用命令:ping / netstat / xargs / pidof / watch

ping:檢測網絡聯通 1. ping 的基本功能2. ping 的工作原理3. ping 的常見用法4. ping 的輸出解釋5. ping 的應用場景6. 注意事項 netstat:查看網絡狀態 1. netstat 的基本功能2. 常見用法3. 示例4. 輸出字段解釋5. netstat 的替代工具6. 注意事項 xargs&…

【C++】:STL詳解 —— list類

目錄 list的概念 list的構造函數 list的大小 size() resize() empty() list的插入 push_front()和emplace_front() push_back()和emplace_back() insert()和emplace() list的刪除 pop_front() pop_back() erase() remove() remove_if() unique() clear()…

【數據結構】(11) Map 和 Set

一、Map 和 Set 的簡介 1、Set 和 Map Map 和 Set 是集合類框架學習的最后一部分。Map 和 Set 都是接口,需要通過 TreeSet、HashSet 和 TreeMap、HashMap 實例化。注意,Set 實現了 Collection,Map 并沒有。 Set 存放的是鍵(Key&a…

關于CanvasRenderer.SyncTransform觸發調用的機制

1)關于CanvasRenderer.SyncTransform觸發調用的機制 2)小游戲Spine裁剪掉幀問題 3)Dedicated Server性能問題 4).mp4視頻放入RT進行渲染的性能分析閉坑指南 這是第421篇UWA技術知識分享的推送,精選了UWA社區的熱門話題…

Kronecker分解(K-FAC):讓自然梯度在深度學習中飛起來

Kronecker分解(K-FAC):讓自然梯度在深度學習中飛起來 在深度學習的優化中,自然梯度下降(Natural Gradient Descent)是一個強大的工具,它利用Fisher信息矩陣(FIM)調整梯度…

【HTML— 快速入門】HTML 基礎

準備工作 vscode下載 百度網盤 Subline Text 下載 Sublime Text下載 百度網盤 vscode 下載 Sublime Text 是一款輕量好用的文本編輯器,我們在寫前端代碼時,使用 Sublime Text 打開比使用記事本打開,得到的代碼體驗更好,比 vscode…

鴻蒙開發深入淺出01(基本環境搭建、頁面模板與TabBar)

鴻蒙開發深入淺出01(基本環境搭建、頁面模板與TabBar) 1、效果展示2、下載 DevEco Studio3、創建項目4、新建頁面模板5、更改應用信息6、新建以下頁面7、Index.ets8、真機運行9、圖片資源文件 1、效果展示 2、下載 DevEco Studio 訪問官網根據自己的版本…

自動駕駛泊車算法詳解(一)

自動駕駛泊車算法是自動駕駛技術中的重要組成部分,主要用于實現車輛在復雜場景下的自動泊車功能(如垂直泊車、側方位泊車、斜列泊車等)。其核心目標是通過感知、規劃和控制技術,使車輛在無人工干預的情況下安全、高效地完成泊車動…

鴻蒙next 點擊穿透實現

點擊穿透可以參考華為開發的保留文章,該章節只能在developer preview版本下查看 點擊穿透 主要的方法是hitTestBehavior // xxx.ets Entry Component struct HitTestBehaviorExample {build() {// outer stackStack() {Button(outer button).onTouch((event) > {console.i…

27.[前端開發-JavaScript基礎]Day04-函數基本使用-遞歸-變量作用域-函數式編程

一、JavaScript函數 1 認識JavaScript函數 程序中的foo、bar、baz 認識函數 函數使用的步驟 2 函數的聲明和調用 聲明和調用函數 函數的參數 有參數的函數練習 函數的返回值 函數的練習 arguments參數(JS高級再學習) 3 函數的遞歸調用 函數中調用函數…

藍橋杯練習代碼

一、最長公共前綴 編寫一個函數來查找字符串數組中的最長公共前綴。 如果不存在公共前綴,返回空字符串 ""。 示例 1: 輸入:strs = ["flower","flow","flight"] 輸出:"fl"示例 2: 輸入:strs = ["dog",&q…

添加成對約束后的標簽傳播算法研究:使用Python語言編寫算法,在空手道數據集下驗證算法的準確性,在一定程度上解決非對齊問題

背景: 輔導的過程中遇到了一個比較新穎的問題,下面是我對這個問題的分析和簡要思路介紹。 思路分析: 這算機器學習下面的無監督學習,標簽傳播算法簡稱LPA,傳統的標簽傳播算法會出現非對齊問題,一句話描述就…