前端JS: 浅拷贝,深拷贝

5 阅读1分钟

JS 浅拷贝与深拷贝详解

一、基本概念

浅拷贝:只拷贝对象的第一层属性,深层属性仍然是引用

深拷贝:完全拷贝整个对象,包括所有嵌套对象,新旧对象完全独立

二、浅拷贝的实现方式

1. 扩展运算符

const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { ...obj1 };
obj2.b.c = 3;
console.log(obj1.b.c); // 3 (共享引用)

2. Object.assign()

const obj1 = { a: 1, b: { c: 2 } };
const obj2 = Object.assign({}, obj1);

三、深拷贝的实现方式

1. JSON 方法(最简单,但有局限)

const obj1 = { a: 1, b: { c: 2 } };
const obj2 = JSON.parse(JSON.stringify(obj1));

// 缺点:不支持函数、undefined、Symbol、循环引用、Date等特殊对象

2. 递归实现

function simpleDeepCopy(obj) {
  // 如果是基本类型,直接返回
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  
  // 如果是数组
  if (Array.isArray(obj)) {
    return obj.map(item => simpleDeepCopy(item));
  }
  
  // 如果是对象
  let newObj = {};
  for (let key in obj) {
    newObj[key] = simpleDeepCopy(obj[key]);
  }
  return newObj;
}

// 使用示例
let original = {
  a: 1,
  b: { c: 2 },
  d: [1, 2, { e: 3 }]
};

let copied = simpleDeepCopy(original);
copied.b.c = 999;
copied.d[2].e = 888;

console.log(original.b.c);  // 2 - 没变 ✓
console.log(original.d[2].e);  // 3 - 没变 ✓

四、使用场景与选择建议

使用浅拷贝的场景

  • 数据对象层级简单,没有嵌套对象
  • 需要共享部分数据引用
  • 性能要求较高

使用深拷贝的场景

  • 需要完全独立的数据副本
  • 数据修改不影响原对象
  • 处理复杂嵌套结构

最推荐的方法

// 记住这个例子就够了:
let source = { a: 1, b: { c: 2 } };

// ❌ 这样不行(共享所有)
let wrong = source;

// ⚠️ 这样有风险(共享深层)
let shallow = { ...source };

// ✅ 这样安全(完全独立)
let deep1 = JSON.parse(JSON.stringify(source));  // 简单场景
let deep2 = structuredClone(source);  // 现代方案 最佳方案(ES2022+)
let deep3 = _.cloneDeep(source);  // Lodash方案  兼容性好的方案