浅副本和深副本

浅拷贝与深拷贝:JavaScript 对象复制详解

本文深入探讨 javascript 中的浅拷贝和深拷贝,并通过示例代码清晰地展现两者之间的差异。理解这两种拷贝方式对于避免潜在的程序错误至关重要。

1. 浅拷贝

浅拷贝创建一个新对象,但只复制顶层属性。对于嵌套对象或数组,浅拷贝只复制其引用,而非创建新的副本。这意味着,修改浅拷贝中的嵌套对象会同时影响原始对象。

示例 1:使用 Object.assign() 进行浅拷贝

const original = {  name: "john",  age: 30,  address: {    city: "new york",    zip: "10001"  }};const shallowCopy = Object.assign({}, original);shallowCopy.address.city = "los angeles";console.log(original.address.city); // 输出: "los angeles"console.log(shallowCopy.address.city); // 输出: "los angeles"

登录后复制

说明: Object.assign() 只复制了原始对象的顶层属性。address 属性仍然指向同一个内存地址,因此修改 shallowCopy.address 也改变了 original.address。

示例 2:使用展开运算符进行浅拷贝

const book = {  title: 'javascript guide',  author: 'john doe',  publisher: {    name: 'tech books',    year: 2020  }};const bookCopy = { ...book };bookCopy.publisher.year = 2023;console.log(book.publisher.year); // 输出: 2023console.log(bookCopy.publisher.year); // 输出: 2023

登录后复制

说明: 展开运算符也执行浅拷贝,嵌套对象的修改同样会影响原始对象。

示例 3:使用 slice() 方法对数组进行浅拷贝

const numbers = [1, 2, [3, 4]];const numbersCopy = numbers.slice();numbersCopy[2][0] = 99;console.log(numbers); // 输出: [1, 2, [99, 4]]console.log(numbersCopy); // 输出: [1, 2, [99, 4]]

登录后复制

说明: slice() 创建数组的浅拷贝。修改嵌套数组会影响原始数组,因为嵌套数组的引用被复制了。

示例 4:包含数组的对象的浅拷贝

const config = {  theme: 'dark',  colors: ['red', 'green'],};const configCopy = Object.assign({}, config);configCopy.colors[0] = 'yellow';console.log(config); // 输出: {theme: 'dark', colors: ['yellow', 'green']}console.log(configCopy); // 输出: {theme: 'dark', colors: ['yellow', 'green']}

登录后复制

说明: 修改 colors 数组会影响原始对象,因为 colors 数组的引用被复制了。

2. 深拷贝

深拷贝创建对象的完全独立副本,包括所有嵌套对象和数组。修改深拷贝不会影响原始对象,反之亦然。

示例:使用 JSON.parse(JSON.stringify(original)) 进行深拷贝

const original = {  name: "john",  age: 30,  address: {    city: "new york",    zip: "10001"  }};const deepCopy = JSON.parse(JSON.stringify(original));deepCopy.address.city = "los angeles";console.log(original.address.city); // 输出: "new york"console.log(deepCopy.address.city); // 输出: "los angeles"

登录后复制

说明: JSON.stringify() 将对象转换为 JSON 字符串,JSON.parse() 将 JSON 字符串解析回新的对象。这创建了一个完全独立的副本。

深拷贝与浅拷贝的差异:

特性 浅拷贝 深拷贝

速度快慢内存占用少多嵌套对象/数组只复制引用,修改会影响原始对象创建新的副本,修改不会影响原始对象适用场景简单的对象复制,性能要求高的情况复杂的嵌套对象,需要完全独立的副本的情况局限性无法复制函数、日期等特殊对象类型JSON.parse(JSON.stringify()) 无法处理函数、正则表达式、Date 对象等

警告: 使用 JSON.parse(JSON.stringify()) 进行深拷贝的局限性:

它不能复制函数、undefined、正则表达式、Date 对象或循环引用。它可能无法保留特殊对象类型(例如,Map,Set)。

对于更复杂的深拷贝需求,建议使用 Lodash 的 _.cloneDeep() 等工具函数。

浅副本和深副本

选择浅拷贝还是深拷贝取决于具体的应用场景。如果只需要复制简单的对象,并且性能是关键因素,那么浅拷贝是合适的。如果需要完全独立的副本,并且可以承受一定的性能损耗,那么深拷贝是更好的选择。

以上就是浅副本和深副本的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2640579.html

(0)
上一篇 2025年3月7日 06:20:21
下一篇 2025年2月24日 19:45:20

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 使用我们的业务电子邮件数据库与德国的主要决策者联系

    德国是欧洲经济强国,对寻求拓展业务的企业而言至关重要。ready mailing团队提供的德国企业邮箱数据库,让您的企业能够接触到来自it、金融、医疗、零售等多个行业的数千个已验证联系人。这个全面且符合gdpr的数据库,旨在帮助您精准定位目…

    2025年3月7日
    200
  • 为您的React应用程序选择正确的CSS方法

    React应用的样式化方法多种多样,选择哪种方法取决于个人喜好、项目需求和团队协作。以下列举了五种常见的React应用CSS方法。 1. 标准CSS 在独立的.css文件中编写CSS代码,然后导入到React组件中。 /* styles.c…

    2025年3月7日
    200
  • 将可重复使用的API逻辑用于节点应用

    在构建后端服务时,您是否经常发现自己编写相似的API逻辑? 通常,我们会将这些代码片段保存在Git仓库中,或者使用自定义启动模板。 但是,您知道可以通过安装npm模块来重用这些API逻辑吗? Vratix私有API模块允许您创建自己的私有注…

    2025年3月7日
    200
  • 反应性组件热加载与状态保存

    现代网络开发追求快速、流畅的用户体验。然而,传统的全页刷新机制在应用代码更改时会清除用户输入、身份验证数据和导航历史,迫使开发者每次更新后都重新搭建测试环境。热重载技术应运而生,它在保持应用状态的同时实时更新代码,显著提升了开发效率。 热重…

    2025年3月7日
    200
  • 通过js中的参考来呼叫/通过价值和通话/通过参考

    本文探讨JavaScript中按值和按引用传递数据的方式,以及原始数据类型和非原始数据类型之间的差异。 原始数据类型 vs. 非原始数据类型 JavaScript中的数据类型分为原始类型和非原始类型(也称为引用类型)。 原始数据类型是不可变…

    2025年3月7日
    200
  • JS中的简单内存数据库

    大家好! 我最近完成了一个很有趣的项目:一个基于JavaScript的简易内存数据库。这个项目的目标是提升我对对象回收机制的理解,并深入学习数据库底层运作原理。 我特别想实现一种直观的查询功能,能够进行数据过滤操作,这在很多项目中都非常实用…

    2025年3月7日
    200
  • 购买核桃幼苗及其要点

    高产经济核桃园建设的关键:选购优质核桃苗 选择合适的核桃苗是打造高产值、经济型核桃园的第一步。核桃苗的品种、气候适应性、抗病性以及最终产量都大相径庭。本文将重点介绍选购核桃苗的关键因素。 优质核桃苗的重要性 健康的核桃苗是成功种植的关键。优…

    2025年3月7日
    200
  • JavaScript对象魔术

    本文探讨JavaScript对象赋值的特性及其潜在问题,并提供解决方案。 对象赋值与引用: 以下代码片段演示了JavaScript对象赋值的机制: const person = { firstname: ‘ajay’, lastname: …

    2025年3月7日
    200
  • 了解Libuv及其线程池

    本文最初发表于我的博客,原文链接如下: 深入理解libuv及其线程池机制 本文将深入探讨libuv库的功能,并重点分析其核心特性之一:线程池。 rahulvijayvergiya.hashnode.dev 即使您对libuv并不熟悉,只要您…

    2025年3月7日
    200
  • 在Nodejs的引擎盖下:探索VavaScript引擎

    本文最初发表于我的博客,原文链接如下: 深入V8 JavaScript引擎 V8引擎如何赋予Node.js超高效率?本文将深入探讨V8的内部机制。 rahulvijayvergiya.hashnode.dev V8引擎是JavaScript…

    2025年3月7日
    200

发表回复

登录后才能评论