详细聊聊JS中不一样的深拷贝

yizhihongxing

下面我将详细讲解JS中不一样的深拷贝的完整攻略。

什么是深拷贝

深拷贝是指将一个对象完整复制一份并生成一个新对象,新对象和旧对象互不影响,即使新对象被修改了,旧对象也不会发生改变。

JavaScript 中的深拷贝

在 JavaScript 中,拷贝对象的方法是 Object.assign() 或者使用扩展运算符 ...。然而,这些拷贝方法都只能进行浅拷贝。

浅拷贝只是复制了对象的第一层级属性,如果是一个嵌套的对象就会出现问题。比如一个对象的属性值是一个引用类型,那么浅拷贝会复制这个引用类型的内存地址,新旧对象的这一属性的值就会指向同一个内存地址。

因此,如果要进行深拷贝,需要使用其他方法或者手动实现深拷贝的方法。下面介绍两种比较常见的深拷贝方式。

JSON.parse(JSON.stringify(obj))

使用 JSON.parse(JSON.stringify(obj)) 可以实现深拷贝。它的原理是利用 JSON.stringify() 将原对象序列化成一个 JSON 字符串,再利用 JSON.parse() 将这个 JSON 字符串解析成一个新的对象,这个新的对象与原对象没有任何的引用关系。

但是,这个方法是有限制的,它只能序列化那些 JSON 能够表示的数据类型,而不能序列化那些不能被表示为 JSON 的数据类型,比如 undefined 和 function。

代码示例:

function deepCopy(obj) {
  return JSON.parse(JSON.stringify(obj))
}

let oldObj = {name: '张三', age: 18, info: {hobby: 'basketball'}}
let newObj = deepCopy(oldObj)

console.log(oldObj.age)    // 18
console.log(newObj.age)    // 18

oldObj.age = 20
console.log(oldObj.age)    // 20
console.log(newObj.age)    // 18

oldObj.info.hobby = 'football'
console.log(oldObj.info.hobby)    // football
console.log(newObj.info.hobby)    // basketball

可以看到,使用这种方式进行深拷贝,无法复制原始对象中的引用类型,修改原始对象的引用类型会影响复制后的引用类型。

递归实现

另外一种方法是手动实现递归拷贝,递归遍历对象,复制对象的每一个属性,直到遍历到属性值为基本类型时结束递归。

代码示例:

function deepCopy(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj
  }

  let newObj = Array.isArray(obj) ? [] : {}

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = deepCopy(obj[key])
    }
  }

  return newObj
}

let oldObj = {name: '张三', age: 18, info: {hobby: 'basketball'}}
let newObj = deepCopy(oldObj)

console.log(oldObj.age)    // 18
console.log(newObj.age)    // 18

oldObj.age = 20
console.log(oldObj.age)    // 20
console.log(newObj.age)    // 18

oldObj.info.hobby = 'football'
console.log(oldObj.info.hobby)    // football
console.log(newObj.info.hobby)    // basketball

可以看到,使用递归实现深拷贝,能够完整复制原始对象中的引用类型,修改原始对象的引用类型不会影响复制后的引用类型。

总结

以上两种方法都可以实现深拷贝,但是第一种方法是将原始对象序列化成字符串,然后又通过解析字符串生成一个新的对象,可能会带来额外的性能开销。而第二种方法是完全手写,需要自己实现递归遍历,并创建新的对象,相对而言比较繁琐。需要根据自己的实际业务需求选择适合的深拷贝实现方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详细聊聊JS中不一样的深拷贝 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • JS 加入收藏夹的代码(主流浏览器通用)

    这里提到的“JS 加入收藏夹的代码(主流浏览器通用)”是指使用JavaScript代码实现将当前网页添加到收藏夹中的功能,下面是详细讲解完整攻略: 步骤一:创建添加收藏夹的代码段 我们可以使用Javascript创建一个函数,将当前网页添加到收藏夹,并返回true或false来表示是否添加成功。下面是一个示例代码: function addFavorite(…

    JavaScript 2023年5月27日
    00
  • javascript url几种编码方式详解

    JavaScript URL几种编码方式详解 在JavaScript中,对URL进行编码是一项常见的任务。URL编码是将URL中的字符串转换为可安全传输的格式的过程。在编码URL之前,需要了解几种不同的URL编码方式以及它们的适用场景。 encodeURIComponent() encodeURIComponent() 是Javascript中常用的编码函数…

    JavaScript 2023年5月20日
    00
  • js设置和获取自定义属性的方法

    关于JS设置和获取自定义属性的方法,我们可以分为以下两种: 1. 使用.dataset属性 通过设置dataset属性,我们可以在HTML元素中定义自定义属性,这些属性可以是任何名称,并且可以作为一个无结构数据来处理,类似于JSON格式的键值对。 1.1 设置自定义属性 通过设置dataset属性,我们可以轻松地在JS中定义HTML元素的自定义属性,方法如下…

    JavaScript 2023年6月10日
    00
  • JS实现的在线调色板实例(附demo源码下载)

    JS实现的在线调色板实例 本篇文章将向您展示如何使用JavaScript创建一个在线调色板实例。本项目使用HTML、CSS和JS,允许用户通过单击颜色选取器调整颜色,然后显示所选颜色的值。 项目代码 请先下载示例代码,然后跟随我们的指导进行实现:在线调色板实例源代码 实现过程 从Github仓库中下载示例代码。 用您最喜欢的编辑器打开index.html文件…

    JavaScript 2023年6月10日
    00
  • JS数组操作(数组增加、删除、翻转、转字符串、取索引、截取(切片)slice、剪接splice、数组合并)

    JS数组操作是对数组进行增加、删除、翻转、转字符串、取索引、截取、剪接和数组合并等常见操作。 增加操作 数组的增加操作包括push和unshift,push用于在数组末尾添加一个或多个元素,unshift用于在数组开头添加一个或多个元素。示例如下: let arr = [1, 2, 3]; // push arr.push(4); console.log(a…

    JavaScript 2023年5月27日
    00
  • 关于JavaScript跨域问题及实时刷新解决方案

    关于JavaScript跨域问题及实时刷新解决方案 什么是跨域 跨域是指在一个域名下使用了另一个域名的资源。如从www.domain1.com的域名下的页面中向www.domain2.com发起ajax请求,就是跨域操作。 常见的跨域场景 域名不同 协议不同 端口不同 JavaScript跨域问题的原因 从浏览器的安全限制出发,浏览器禁止页面使用其它域名下的…

    JavaScript 2023年6月11日
    00
  • JavaScript学习点滴 call、apply的区别

    讲解“JavaScript学习点滴 call、apply的区别”的完整攻略如下: 一、call和apply的概念 在Javascript中,所有对象都可以调用call和apply方法,它们的作用都是改变函数体内this的指向。两者的区别在于传入参数的形式不同。 call和apply都是定义在Function.prototype上的方法,因此可以被所有的函数对…

    JavaScript 2023年6月10日
    00
  • ant-design-vue 实现表格内部字段验证功能

    Ant Design Vue 是一个开箱即用的中后台前端/设计解决方案,它提供了丰富的 UI 组件,使得快速开发高质量的应用程序成为可能。其中 Ant Design Vue 的表格组件支持表单内字段的验证功能,下面我将详细讲解该如何使用 ant-design-vue 实现表格内部字段验证功能。 步骤一:引入 ant-design-vue 首先需要在项目中引入…

    JavaScript 2023年6月10日
    00
合作推广
合作推广
分享本页
返回顶部