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
}

总结

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

相关推荐
绝无仅有14 小时前
Go 语言面试之通道 (Channel) 解密
后端·面试·github
前端fighter14 小时前
Async/Await 实现原理
前端·javascript·面试
前端小巷子14 小时前
Vue3 模板编译优化
前端·vue.js·面试
不爱说话郭德纲14 小时前
🔥面试官:说说看,用户登录后拿到的 Token,你应该怎么存?存哪里?
前端·安全·面试
艾小码14 小时前
React 渲染流程深度解析(结合 react-reconciler)
前端·javascript·react.js
Hy行者勇哥14 小时前
生成知识图谱与技能树的工具指南:PlantUML、Mermaid 和 D3.js
javascript·人工智能·知识图谱
一只毛驴14 小时前
视频播放器的编解码
前端·javascript
Chaoran14 小时前
浏览器加载外部资源性能优化
前端·javascript·面试
子兮曰14 小时前
别再手动处理API数据了!这个BFF数据转换层让你的开发效率提升300%
前端·javascript·api
知识分享小能手14 小时前
React学习教程,从入门到精通, React 入门指南:创建 React 应用程序的语法知识点(7)
前端·javascript·vue.js·学习·react.js·前端框架·anti-design-vue