JavaScript 中的深拷贝与浅拷贝

在 JavaScript 中,对象的复制通常分为两种类型:深拷贝和浅拷贝。这两种拷贝方式在处理对象和数组时有不同的影响,因此在开发中选择适当的拷贝方式非常重要。让我们深入了解这两种拷贝方式以及它们的区别。

1. 浅拷贝

浅拷贝是指复制一个对象,创建一个新对象,但仅复制原始对象的第一层结构。换句话说,如果原始对象包含引用类型(例如对象或数组),则浅拷贝只会复制引用而不会复制引用指向的对象本身。

1.1 使用 Object.assign()

js 复制代码
const originalObject = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, originalObject);

console.log(shallowCopy);
// 输出: { a: 1, b: { c: 2 } }

console.log(originalObject.b === shallowCopy.b);
// 输出: true

1.2 使用展开运算符(Spread Operator)

js 复制代码
const originalObject = { a: 1, b: { c: 2 } };
const shallowCopy = { ...originalObject };

console.log(shallowCopy);
// 输出: { a: 1, b: { c: 2 } }

console.log(originalObject.b === shallowCopy.b);
// 输出: true

浅拷贝的缺点在于,如果原始对象的属性值是引用类型,那么浅拷贝后的对象仍然会共享这些引用类型的值。

2. 深拷贝

深拷贝是指创建一个新对象,并递归地复制原始对象的所有嵌套属性,包括引用类型。这确保了原始对象和拷贝后的对象是完全独立的,不共享任何引用类型的值。

2.1 使用递归实现深拷贝

js 复制代码
function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // 非对象或 null 直接返回
  }

  let copy = Array.isArray(obj) ? [] : {};

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }

  return copy;
}

const originalObject = { a: 1, b: { c: 2 } };
const deepCopyObject = deepCopy(originalObject);

console.log(deepCopyObject);
// 输出: { a: 1, b: { c: 2 } }

console.log(originalObject.b === deepCopyObject.b);
// 输出: false

2.2 使用 JSON 序列化与反序列化

js 复制代码
const originalObject = { a: 1, b: { c: 2 } };
const deepCopyObject = JSON.parse(JSON.stringify(originalObject));

console.log(deepCopyObject);
// 输出: { a: 1, b: { c: 2 } }

console.log(originalObject.b === deepCopyObject.b);
// 输出: false

需要注意的是,使用 JSON 序列化和反序列化的方法有一些限制,例如无法处理包含函数、正则表达式等特殊对象。

手写一个浅拷贝

js 复制代码
function shalldowCopy(obj) {
  if (typeof obj !== 'object' || obj == null) return  //只拷贝引用类型
  let objCopy = obj instanceof Array ? [] : {}
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      objCopy[key] = obj[key]
    }
  }
  return objCopy
}

总结

选择深拷贝还是浅拷贝取决于你的需求。浅拷贝通常足够满足简单的场景,但在涉及复杂嵌套结构、共享状态或需要保留原始对象与拷贝对象完全独立的情况下,深拷贝是更安全的选择。在实际开发中,根据具体情况选择合适的拷贝方式是非常重要的。

相关推荐
芝士爱知识a1 小时前
AI 模拟面试怎么做:智蛙公考智能体多轮对话 + 实时追问的工程实现
面试·职场和发展
帅次2 小时前
Android 高级工程师面试:Java 基础知识 近1年高频追问 22 题
android·java·面试
anOnion3 小时前
Agentic 前端开发之 实时显示 AI Agent 终端输出
前端·javascript·人工智能
这是个栗子3 小时前
【前端性能优化】优化数据加载:用 Promise.all 从串行到并行
前端·javascript·性能优化·异步编程·前端优化·promise.all
fei_sun4 小时前
黑洞路由(Null Route/空接口路由)
服务器·前端·javascript
摇滚侠5 小时前
方法 A 等方法 B 执行完再执行 叫同步调用还是异步调用 JS 默认是同步调用还是异步调用
开发语言·javascript·ecmascript
触底反弹6 小时前
🔥 字符串算法面试三连击:反转、回文、回文变种,搞懂这三题稳了!
前端·javascript·算法
触底反弹6 小时前
AI Tool Use 深度解析:大模型是如何"突破物理限制"调用外部工具的?
javascript·人工智能·后端
竹林8187 小时前
从 RPC 超时到批量签名:我用 @solana/web3.js 重构了一个 NFT 铸造页面,踩了这些坑
前端·javascript
优雅格子衫7 小时前
TypeScript 类的基本使用小结
javascript·ubuntu·typescript