2025好运-JS篇-浅拷贝与深拷贝

64 阅读2分钟

1. 浅拷贝

浅拷贝(Shallow Copy)是指创建一个新对象,仅复制原始对象的第一层属性。若属性是基本类型(如数字、字符串),直接复制值;若属性是引用类型(如对象、数组),则复制内存地址引用(新旧对象共享嵌套数据)

特点

  1. 修改原始对象的基本类型属性不会影响拷贝后的对象
  2. 修改原始对象的引用类型属性(数组元素、对象属性)会影响拷贝后的对象
const original = { a: 1, b: { c: 2 } };
const copy = { ...original };
copy.b.c = 100;
console.log(original.b.c); // 输出 100(原对象被修改!)

实现方式

  1. 使用Object.assign方法
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
  1. 使用对象的扩展运算符{...}
const shallowCopy = Object.assign({}, obj);
  1. 使用sliceconcat方法
const arr = [1, [2, 3]];
const arrCopy = arr.slice();

2. 深拷贝

深拷贝(Deep Copy)是指递归复制对象的所有层级属性,完全创建新的内存空间。新旧对象的所有属性(包括嵌套引用类型)完全独立。

特点

无论修改原始对象的任何属性,拷贝后的对象都不会受到影响

实现方式

  1. 使用JSON.parse(JSON.stringify())
const deepCopy = JSON.parse(JSON.stringify(obj));
  • 缺点:丢失函数、undefinedSymbolDate对象(转为字符串)、无法处理循环引用。
  1. 使用structuredClone()(现代浏览器原生方法)
const deepCopy = structuredClone(obj);
  • 缺点:仍不支持函数、DOM节点。
  1. 使用Lodash的cloneDeep
import _ from 'lodash';
const deepCopy = _.cloneDeep(obj);

3.手写浅拷贝与深拷贝

手写浅拷贝

function shallowCopy(target) {
  // 处理非对象类型(直接返回)
  if (typeof target !== 'object' || target === null) {
    return target;
  }

  // 创建新容器(数组或普通对象)
  const copy = Array.isArray(target) ? [] : {};

  // 遍历并复制第一层属性
  for (const key in target) {
    if (target.hasOwnProperty(key)) {
      copy[key] = target[key]; // 直接赋值(引用类型共享地址)
    }
  }
  return copy;
}

手写深拷贝

function deepClone(target, map = new WeakMap()) {
  // 基本类型直接返回
  if (target === null || typeof target !== 'object') {
    return target;
  }

  // 处理循环引用(避免无限递归)
  if (map.has(target)) {
    return map.get(target);
  }

  // 处理特殊对象类型
  const constructor = target.constructor;
  if (/^(Date|RegExp)$/i.test(constructor.name)) {
    return new constructor(target); // 创建新实例
  }

  // 初始化克隆对象
  const clone = Array.isArray(target) ? [] : {};
  map.set(target, clone); // 记录已拷贝对象

  // 复制Symbol类型属性
  const symKeys = Object.getOwnPropertySymbols(target);
  symKeys.forEach((symKey) => {
    clone[symKey] = deepClone(target[symKey], map);
  });

  // 递归复制所有属性
  for (const key in target) {
    if (target.hasOwnProperty(key)) {
      clone[key] = deepClone(target[key], map);
    }
  }

  return clone;
}

4. 总结

特性浅拷贝 (Shallow Copy)深拷贝 (Deep Copy)
对象独立性新对象与原始对象共享嵌套引用新对象完全独立于原始对象
性能较快(只复制顶层结构)较慢(递归复制所有嵌套对象)
适用场景简单对象或不需要修改嵌套数据时需要完全独立的副本,尤其是嵌套结构时
内存占用较低(共享引用)较高(完全复制)