【JavaScript】🧩JS拷贝三境界:赋值、浅拷贝与深拷贝

21 阅读3分钟

本文内容基于 JavaScript 的内存管理机制,建议先了解变量存储方式

🧠 1. 核心本质:内存管理机制

JavaScript 中的深浅拷贝概念源于引用类型的内存管理机制,本质是为了解决如何独立复制引用类型数据的问题。

数据存储原理:

  • 基本类型:值直接存储在栈空间,复制时创建独立副本
  • 引用类型:值存储在堆空间,变量存储的是内存地址指针
// 基本类型 - 独立复制
let a = 10;
let b = a; 
b = 20;
console.log(a); // 10(不受影响)

// 引用类型 - 共享指针
let obj1 = { x: 1 };
let obj2 = obj1;
obj2.x = 2;
console.log(obj1.x); // 2(被修改)

💡 深浅拷贝主要解决引用类型复制问题,基本类型复制天然独立

🍰 2. 浅拷贝:表层复制

2.1 核心本质

只复制对象的第一层属性,嵌套对象依然共享内存引用

2.2 常用实现方式

方法适用类型特点说明
[...arr]数组简洁高效
Object.assign({}, obj)对象适合合并对象属性
arr.slice()数组可截取片段
[].concat(arr)数组适合合并多个数组
Object.create(obj)对象原型继承(非严格复制)

🛠️ 2.3 手写浅拷贝实现

const obj = {
  name: 'FairyDiana',
  age: 18,
  money: Infinity,
  lovers: {
    one: '肖战',
    two: '木村拓哉'
  }
}

function shallowCopy(obj) {
  let newobj = {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newobj[key] = obj[key];
    }
  }
  return newobj;
}

const obj1 = shallowCopy(obj)
obj1.name = 'diana'
console.log(obj);

obj1.lovers.one = '魏无羡'
console.log(obj);

⚖️ 2.4 直接赋值 vs 浅拷贝

// 直接赋值 - 完全共享内存
const objA = { a: 1, b: { c: 2 } };
const objB = objA; // 完全共享内存地址

// 浅拷贝 - 创建新表层对象
const objC = Object.assign({}, objA); 
// objC.a独立,但objC.b与objA.b共享内存

🧩 3. 深拷贝:完全独立复制

3.1 核心本质

创建对象的完全独立副本,所有层级属性都不共享内存引用

3.2 常用实现方式

方法1:JSON 序列化(简易版)

const deepCopy = JSON.parse(JSON.stringify(obj));

局限性

  • 不支持函数、undefined、Symbol、BigInt
  • 会丢失特殊对象(Date/RegExp)的原型特性
  • 无法处理循环引用

方法2:structuredClone(现代 API)

const deepCopy = structuredClone(obj);

优势

  • 支持 Date、Set、Map 等内置对象
  • 处理循环引用
  • 保持原型特性

限制

  • 不支持函数和 Symbol
  • 浏览器兼容性问题

🛠️ 3.3 手写深拷贝实现(基础版)

const obj = {
  name: "FairyDiana",
  age: 18,
  money: Infinity,
  lovers: {
    one: "肖战",
    two: "木村拓哉",
  },
};

function deepCopy(obj) {
  let newobj = {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (typeof obj[key] === "object") {
        newobj[key] = deepCopy(obj[key]);
      } else {
        newobj[key] = obj[key];
      }
    }
  }
  return newobj;
}

const obj1 = deepCopy(obj);
obj1.name = "diana";
console.log(obj);

obj1.lovers.one = "魏无羡";
console.log(obj);

💎 总结:选择拷贝方式的黄金法则

场景推荐方案原因
简单数据复制浅拷贝性能高效
需要完全独立副本深拷贝避免意外修改
含特殊对象的数据structuredClone保持类型完整性
简单 JSON 数据JSON.parse/stringify快速实现
循环引用数据structuredClone安全处理引用关系

理解本质:深浅拷贝的核心差异在于内存引用关系的复制深度。浅拷贝只断开第一层引用,深拷贝则递归断开所有层级的引用关系,创建真正独立的内存空间。