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
}

总结

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

相关推荐
疯狂SQL5 小时前
JWT 在线解码、验签、生成一篇讲透:附前端实现、工具架构与在线体验地址
javascript·jwt·编解码·jwt测试
前端一小卒5 小时前
不手写代码的第 30 天,我才明白前端这个岗位还剩什么
前端·javascript·ai编程
Ajie'Blog5 小时前
Copilot Agent Tasks API 开放:AI 编程开始进入后台任务时代
服务器·前端·javascript·人工智能·copilot·ai编程
老毛肚5 小时前
jeecgboot vue TS & 模板化 04
前端·javascript·vue.js
晓13135 小时前
【Cocos Creator 2.x】篇——第二章 入门
javascript·游戏引擎
Cosolar6 小时前
LlamaIndex 文档解析与分块策略深度解析
人工智能·面试·架构
Electrolux7 小时前
[onlyoffice-v9]纯前端怎么实现编辑预览office
前端·javascript·github
VidDown7 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
kyriewen8 小时前
我读了一遍 Babel 编译后的 async/await,终于搞懂了它的原理(附 20 行手写实现)
前端·javascript·面试
半岛@少年10 小时前
都是JS,CJS和ESM有什么区别?
javascript·esm·前端模块化·cjs