ES12中的 Object.assign 方法:避免深拷贝对象时的问题

前言

在前端开发中,我们常常需要对对象进行复制、操作和拷贝。在 JavaScript 中,一般情况下,我们使用 Object.assign 方法来对对象进行浅拷贝。但是,当我们需要对多层嵌套的对象进行深拷贝时,会遇到很多问题。ES12 中的 Object.assign 方法提供了一种新的解决方案,让我们更方便地进行操作。

什么是深拷贝?

深拷贝是指复制一个对象,使得新对象与原对象在内存中不共享任何地址空间。当我们修改新对象时,不会影响原对象。

JavaScript 中,对象分为两种类型:基本类型和引用类型。

基本类型,如数字、字符串、布尔值等,存储在栈上,可以直接复制。

引用类型,如数组、对象等,存储在堆上,不能直接复制。复制后,新对象与原对象会共享同一块堆空间,因此修改新对象也会影响原对象。

为什么需要深拷贝?

在开发中,我们常常需要对对象进行值的复制和操作。如果直接复制一个对象,会出现多个变量引用同一个对象的情况,当其中一个变量更改了对象的属性,其他变量的对象属性也会跟着改变。这种情况下,我们需要对对象进行深拷贝。

浅拷贝

在 JavaScript 中,使用 Object.assign() 方法来对对象进行浅拷贝。

----- ------- - -
  -- --
  -- --
  -- -
    -- --
    -- -
  -
--

----- ------- - ----------------- ---------

----------- - --

------------------------- -- ------- -

在上面的示例中,我们使用 Object.assign() 方法将 object1 复制到 object2,然后将 object2c.d 修改为 5。这时再输出 object1.c.d,其值为 5,即原对象被修改。

这是因为 Object.assign() 方法只是将对象的属性值复制到新对象,而对象的属性值如果是一个对象,则复制的是该对象的地址,从而导致新对象和原对象共享同一个根对象。

深拷贝

JavaScript 中,有多种深拷贝的方法,例如遍历原对象并递归复制,使用 JSON 序列化和反序列化等。但这些方法都存在一些问题和限制。

使用 Object.assign 方法进行深拷贝

ES12 中的 Object.assign() 方法提供了一种新的解决方案,可以照顾到多层嵌套对象的情况,使得我们更方便地进行操作。

----- ---- - -
  -- --
  -- -
    -- --
    -- -
  -
--

----- ---- - ----------------- ----- -
  -- ----------------- -------
---

---------------------- -- ------- -
-------- - ---
---------------------- -- ------- -
---------------------- -- ------- --

在上面的示例中,我们使用 Object.assign() 方法进行深拷贝。首先使用 Object.assign() 方法将 obj1 复制到 obj2,然后使用 Object.assign() 方法将 obj1.b 复制到 obj2.b。因为 Object.assign() 方法仅仅复制对象的属性值,所以这时 obj2.b 不再引用原对象 obj1.b,而是复制了一份。

我们修改 obj2.b.c 的值为 20,输出 obj1.b.cobj2.b.c,发现 obj1.b.c 的值仍为 2,而 obj2.b.c 的值已经被修改为 20

用递归函数来进行深拷贝

除了可以使用 Object.assign() 方法进行深拷贝外,我们还可以使用递归函数来进行拷贝操作。

-------- -------------- -
  --- ------ - ------------------ - -- - ---
  --- ---- --- -- ---- -
    -- ------------------------------------------ ----- -
      -- ------- -------- --- -------- -- -------- --- ----- -
        ----------- - --------------------
      - ---- -
        ----------- - ---------
      -
    -
  -
  ------ -------
-

----- ---- - -
  -- --
  -- -
    -- --
    -- -
  -
--

----- ---- - ----------------

---------------------- -- ------- -
-------- - ---
---------------------- -- ------- -
---------------------- -- ------- --

在这个示例中,我们使用一个递归函数 deepClone 来进行深拷贝操作。首先判断传入的对象是否为数组,如果是,则创建一个空数组,并遍历原数组中的元素,递归调用 deepClone 并存储到新数组中。如果传入的对象不是数组,则创建一个空对象,并遍历原对象中的属性,递归调用 deepClone 并存储到新对象中。最后返回新对象。

总结

文中,我们介绍了深拷贝的概念和原因,以及如何用 Object.assign() 方法和递归函数进行深拷贝操作。在实践中,我们应该根据需求选择合适的方法,以减少代码的复杂度和提高代码的性能。

参考资料

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/647bd92a968c7c53b072159b


猜你喜欢

  • PWA 落地,如何解决首页性能瓶颈?

    前言 PWA (Progressive Web App)是一种全新的 Web 应用。通过高度优化的渐进式策略,可以快速、可靠地加载应用程序,提供媲美原生应用程序的用户体验。

    1 年前
  • 从零开始实现基于 WebSocket 的前端实时推送

    从零开始实现基于 WebSocket 的前端实时推送 随着互联网技术的发展,实时推送已经成为开发者们越来越重视的一个功能。在前端开发中,WebSocket 是一种非常好的实现实时推送的方式。

    1 年前
  • ES10 中增加的 Array 的 flatMap 方法使用技巧

    ES10 中增加的 Array 的 flatMap 方法使用技巧 在 ES10 中,JavaScript 对 Array 类型进行了一些增强,其中就包括 flatMap 方法。

    1 年前
  • 在 Deno 中使用 CORS 时遇到问题?

    什么是 CORS? CORS(跨源资源共享)是一项浏览器安全特性,用于保护 Web 应用程序免受来自其他域的恶意攻击。它允许服务器在 HTTP 响应中附加一些特殊的标头,以指示浏览器允许从不同源访问该...

    1 年前
  • Express.js 的错误处理中间件与基于 Promise 的异步处理

    #Express.js 的错误处理中间件与基于 Promise 的异步处理 在 web 应用程序的开发过程中,处理错误是必须要处理的一个事情。Express.js 提供了错误处理中间件来帮助开发者处理...

    1 年前
  • Webpack 构建 Vue SSR 应用的最佳实践

    前端SSR(服务器端渲染)是目前Web应用中的热门技术。Vue作为一种流行的前端框架,提供了开发SSR应用的良好支持。而Webpack则是构建这类应用的主要工具之一。

    1 年前
  • Babel 配置和使用详解

    什么是 Babel? 在前端开发中,我们经常需要使用新的 JavaScript 特性和语法,例如箭头函数、模板字面量、解构赋值等等。但是这些语法并不是所有浏览器都支持。

    1 年前
  • ECMAScript 2020 更新详解:模块 Top-Level await

    ECMAScript 2020 更新详解:模块 Top-Level await ECMAScript 2020 更新引入了一个新的特性:模块 Top-Level await,这是一个极具意义的更新,它...

    1 年前
  • 独家解读:ES7 中新增的属性初始值简写

    在 ES6 中,我们已经可以使用属性简写来声明对象,例如: ----- ---- - ------- ----- --- - --- ----- ---- - - ----- --- -- ...

    1 年前
  • 在 Vue.js 中使用 Chai.expect 来测试组件

    Vue.js 是一款优秀的前端框架,广泛应用于各种 Web 应用程序的开发中。在开发过程中,如何保证组件的质量以及功能的稳定性也是非常重要的一点。在这个过程中,我们可以使用一些流行的测试框架,如 Mo...

    1 年前
  • 医疗无障碍如何落实?—— 盲人可使用的医院引导系统浅析

    背景 随着人们对医疗服务的需求增加,医院的规模和设施也越来越复杂。但对于视障人士来说,如何在医院中准确地找到目的地成了一大挑战。如果建立一套盲人可使用的医院引导系统,将能大大提高视障人士的医疗体验和效...

    1 年前
  • 解决 Sequelize Many-to-Many 关系数据的添加操作 Bug

    在 Sequelize 中,Many-to-Many 是一种常见的关系类型,它通常用于连接两个表,对于此类型的关系,通过 Sequelize 添加数据时,常常会遇到一些问题。

    1 年前
  • # ES6 中如何解决对象的循环引用问题

    ES6 中如何解决对象的循环引用问题 在开发过程中,我们经常会遇到对象之间存在相互依赖的情况。在这些依赖中,如果两个对象彼此引用,则会形成循环引用,这可能会导致内存泄漏等问题。

    1 年前
  • Serverless 应用中的本地开发和集成测试

    什么是 Serverless 应用? Serverless 应用是一种使用云计算平台的方式,其中应用程序逻辑被以函数的形式运行,而无需管理底层服务器或操作系统。在Serverless 应用模式下,应用...

    1 年前
  • Fastify 框架中的安全防范与预防

    Fastify 是一个轻量级的 Node.js Web 服务器框架,由于其出色的性能和易于使用的 API,已被用于许多生产环境中。但是,随着互联网的不断发展,Web 应用程序的安全性越来越成为前端开发...

    1 年前
  • SSE 和 AJAX 的联动方式及选择

    随着 Web 技术的不断发展,前端与后端之间的数据交互越来越复杂,即时通讯、实时数据更新等需求越来越普遍。为了实现这些功能,前端开发中使用的主要有两种方式:SSE 和 AJAX。

    1 年前
  • Cypress 实现自动化测试的最佳实践

    随着前端技术的不断发展,自动化测试在前端开发中变得越来越重要。Cypress 是一个流行的前端自动化测试工具,它具有易于维护的代码、能够模拟真实用户操作和提供实时反馈等优势。

    1 年前
  • Sass 编译后页面不显示的问题解决方法

    Sass 是一种强大的 CSS 预处理器,通过使用 Sass 可以提高 CSS 的可读性、可维护性和可重用性。然而,有时候使用 Sass 编写的样式文件在编译后却无法正常显示在页面上,给我们带来不便。

    1 年前
  • Mongoose 中的更新时钩子详解

    Mongoose 是一个基于 Node.js 的 MongoDB 驱动程序,它提供了一种简洁的方式来定义和操作 MongoDB 的文档。其中,Mongoose 还提供了一系列的钩子函数,使我们可以在执...

    1 年前
  • 利用 RxJS 实现自定义 debounce 函数

    在前端开发中,我们经常会遇到需要对用户的输入进行防抖处理的场景,以避免频繁地触发请求或其他操作。而 RxJS 是一个强大的响应式编程库,其中的 debounce 操作符可以方便地实现防抖功能。

    1 年前

相关推荐

    暂无文章