首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

JavaScript 深拷貝實現:JSON 序列化與遞歸拷貝方案

     編輯:程式設計疑難解答

問題背景

JavaScript 中對象屬於引用類型,直接賦值傳遞的是引用地址。需獲取一份值相同但內存獨立的拷貝(深拷貝)。

方案一:JSON 序列化法(簡單、適用純數據對象)

function deepClone(obj) {
    return JSON.parse(JSON.stringify(obj));
}

// 使用示例
const original = { a: 1, b: { c: 2 } };
const cloned = deepClone(original);
cloned.b.c = 99;
console.log(original.b.c); // 2,未受影響

局限性

  • 無法處理 Function、RegExp、Date、undefined、Symbol 類型。
  • 會丟失原型鏈,構造函數變為 Object。
  • 循環引用會拋出錯誤:Converting circular structure to JSON。
  • 方案二:遞歸深拷貝(通用、生產環境推薦)

    function deepClone(obj, hash = new WeakMap()) {
        // 基礎類型直接返回
        if (obj === null || typeof obj !== 'object') return obj;
        
        // 日期、正則等特殊對象
        if (obj instanceof Date) return new Date(obj);
        if (obj instanceof RegExp) return new RegExp(obj);
        
        // 處理循環引用
        if (hash.has(obj)) return hash.get(obj);
        
        // 創建新對象/數組,保持原型
        const clone = Array.isArray(obj) ? [] : Object.create(Object.getPrototypeOf(obj));
        hash.set(obj, clone);
        
        // 遞歸拷貝所有自有屬性(含 Symbol)
        Reflect.ownKeys(obj).forEach(key => {
            clone[key] = deepClone(obj[key], hash);
        });
        
        return clone;
    }
    

    方案三:成熟庫(Lodash / RFDC)

    // Lodash
    import cloneDeep from 'lodash/cloneDeep';
    const cloned = cloneDeep(original);
    
    // RFDC (Really Fast Deep Clone) - 性能極佳
    const rfdc = require('rfdc')();
    const cloned = rfdc(original);
    

    選型建議

    場景推薦方案
    純 JSON 數據、無特殊類型、無循環引用JSON.parse(JSON.stringify())
    通用業務對象、含 Date/RegExp、可能循環引用自定義遞歸函數或 Lodash.cloneDeep
    高性能場景、大對象頻繁拷貝RFDC

    理解深淺拷貝區別,根據業務場景選擇合適方案,避免因引用共享導致的難以排查的數據污染 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved