前置知识: JavaScript

深拷贝与浅拷贝

2 minIntermediate2026/6/14

JavaScript深拷贝与浅拷贝详解:structuredClone、JSON方案缺陷与自定义实现。

1. 浅拷贝

1.1 浅拷贝方法

const original = { a: 1, b: { c: 2 } };

// Object.assign
const copy1 = Object.assign({}, original);

// 展开运算符
const copy2 = { ...original };

// Array.prototype.slice(数组)
const arr = [1, 2, 3];
const arrCopy = arr.slice();

// Array.from
const arrCopy2 = Array.from(arr);

1.2 浅拷贝的问题

const original = { a: 1, b: { c: 2 } };
const copy = { ...original };

copy.a = 100; // 不影响 original
copy.b.c = 200; // 影响 original!b 是引用类型

console.log(original.b.c); // 200 — 浅拷贝只复制引用

2. JSON 序列化方案

2.1 基本用法

const original = { name: 'Alice', age: 30, hobbies: ['reading', 'coding'] };
const deepCopy = JSON.parse(JSON.stringify(original));

deepCopy.hobbies.push('gaming');
console.log(original.hobbies); // ['reading', 'coding'] — 不受影响

2.2 JSON 方案的缺陷

缺陷示例
忽略 undefined{ a: undefined }{}
忽略函数{ fn: () => {} }{}
忽略 Symbol{ [Symbol('x')]: 1 }{}
忽略原型链new Date() → 字符串
循环引用报错obj.self = obj → TypeError
特殊对象丢失Map, Set, RegExp, Buffer{}或异常
NaN/Infinity变成 null
日期变字符串new Date()"2026-06-14T..."
const obj = {
  undefined: undefined,
  fn: () => console.log('hello'),
  date: new Date(),
  regex: /pattern/gi,
  map: new Map([['key', 'value']]),
  set: new Set([1, 2, 3]),
  nan: NaN,
  infinity: Infinity,
  bigInt: 9007199254740991n, // TypeError!
};

JSON.parse(JSON.stringify(obj));
// { date: "2026-06-14T...", regex: {}, map: {}, set: {}, nan: null, infinity: null }

3. structuredClone

3.1 基本用法

const original = {
  date: new Date(),
  regex: /pattern/gi,
  map: new Map([['key', 'value']]),
  set: new Set([1, 2, 3]),
  arrayBuffer: new ArrayBuffer(8),
  nested: { a: { b: 1 } },
};

const clone = structuredClone(original);

clone.nested.a.b = 999;
console.log(original.nested.a.b); // 1 — 深拷贝成功
clone.map.set('new', 'entry');
console.log(original.map.has('new')); // false — Map 独立

3.2 支持的

structuredCloneJSON
基本
Date(变字符串)
RegExp(变 {}
Map / Set(变 {}
ArrayBuffer
TypedArray
Blob
ImageData
循环引用
undefined
函数
Symbol
DOM 节点
Error

3.3 循环引用

const obj = { name: 'circular' };
obj.self = obj;

const clone = structuredClone(obj); //  正常工作
console.log(clone.self === clone); // true
console.log(clone.self === obj); // false

3.4 转移对象

const buffer = new ArrayBuffer(1024);
const clone = structuredClone(buffer, { transfer: [buffer] });
// buffer 被"转移"到 clone,原始 buffer 变为 0 字节
console.log(buffer.byteLength); // 0
console.log(clone.byteLength); // 1024

4. 自定义深拷贝

4.1 基础实现

function deepClone(obj, cache = new WeakMap()) {
  // 基本类型
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  // 循环引用
  if (cache.has(obj)) {
    return cache.get(obj);
  }

  // Date
  if (obj instanceof Date) {
    return new Date(obj);
  }

  // RegExp
  if (obj instanceof RegExp) {
    return new RegExp(obj.source, obj.flags);
  }

  // Map
  if (obj instanceof Map) {
    const clone = new Map();
    cache.set(obj, clone);
    obj.forEach((value, key) => {
      clone.set(deepClone(key, cache), deepClone(value, cache));
    });
    return clone;
  }

  // Set
  if (obj instanceof Set) {
    const clone = new Set();
    cache.set(obj, clone);
    obj.forEach((value) => {
      clone.add(deepClone(value, cache));
    });
    return clone;
  }

  // Array
  if (Array.isArray(obj)) {
    const clone = [];
    cache.set(obj, clone);
    obj.forEach((item, index) => {
      clone[index] = deepClone(item, cache);
    });
    return clone;
  }

  // 普通对象
  const clone = Object.create(Object.getPrototypeOf(obj));
  cache.set(obj, clone);

  // 复制所有自有属性(包括 Symbol)
  Reflect.ownKeys(obj).forEach((key) => {
    clone[key] = deepClone(obj[key], cache);
  });

  return clone;
}

4.2 保留函数引用

function deepCloneWithFunctions(obj, cache = new WeakMap()) {
  if (typeof obj === 'function') {
    // 函数不克隆,直接返回引用
    return obj;
  }
  // 其余逻辑同上...
}

5. 性能对比

数据量: 10000 个嵌套对象

| 方法              | 耗时     | 支持类型 |
| ----------------- | -------- | -------- |
| JSON.parse/stringify | ~15ms | 有限    |
| structuredClone   | ~8ms     | 广泛    |
| 自定义 deepClone  | ~25ms    | 最灵活  |
| 浅拷贝 (...)      | ~1ms     | 仅一层  |

选择建议:

  • 简单数据(纯 JSON 兼容):JSON.parse(JSON.stringify())structuredClone
  • 包含 Date/Map/Set/RegExp:structuredClone
  • 包含函数/特殊对象:自定义 deepClone
  • 仅一层嵌套:浅拷贝 ...