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
}

总结

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

相关推荐
苦瓜小生16 分钟前
【前端】【力扣与手撕】十天带你刷完前端算法与手撕,全是最简单好记的最优解法!day4
前端·数据结构·算法·leetcode·面试
mayaairi26 分钟前
Vue2 实战进阶:表单数据收集、指令系统与自定义指令全解析
前端·javascript·vue.js
图扑软件1 小时前
下篇・换墨|主题/多语言/移动端,一套组件全覆盖
前端·javascript·ui·性能优化·数据可视化
AIsoft_86881 小时前
最好用的会议纪要APP怎么选?功能横评
面试·职场和发展·iphone
胖少年2 小时前
Vitest 5 正式发布实测:Node 22 起步、expect 内联、poll 超时会挂,3.8 亿月下载量的测试框架本周换代
javascript
雪芽蓝域zzs2 小时前
Vue3 defineProps` / `defineEmits` 是编译器宏,不需要手动 import 导入
前端·javascript·vue.js
whyweplay3 小时前
Elpis:从Json Schema 到 页面
前端·javascript
小白羊丨3 小时前
问数 Agent 整体架构、意图识别、历史上下文与 NL2SQL
java·面试·架构
大牧师3 小时前
Nest.js 微服务入门教程
开发语言·javascript·后端·微服务·node.js·nest.js·nest
低代码布道师3 小时前
外包项目管理平台全栈实战课02搭建数据底座:Next.js + PostgreSQL + Prisma 7
开发语言·javascript·postgresql·全栈开发