首页 > 编程语言 >JavaScript深拷贝的具体实现方法解析

JavaScript深拷贝的具体实现方法解析

时间:2023-09-12 19:37:57浏览次数:39  
标签:copy obj 递归 对象 JavaScript deepCopy 拷贝 解析

什么是深拷贝?

深拷贝是指创建一个新对象或数组,使其与原始对象或数组具有相同的值,但是两者是完全独立的,互不影响。深拷贝不仅复制了对象或数组本身,还递归复制了其所有嵌套的对象和数组,确保所有层级的数据都是独立的。

实现深拷贝的方法

在JavaScript中,实现深拷贝的方法有很多种,下面将介绍两种常见的方法。

1. 递归拷贝

递归拷贝是一种常见且简单的实现方法,它通过递归地遍历对象的属性或数组的元素,并对每个属性或元素进行拷贝。

function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // 如果是基本数据类型或 null,直接返回
  }
  
  let copy;
  
  if (Array.isArray(obj)) {
    copy = [];
    for (let i = 0; i < obj.length; i++) {
      copy[i] = deepCopy(obj[i]); // 递归拷贝数组元素
    }
  } else {
    copy = {};
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        copy[key] = deepCopy(obj[key]); // 递归拷贝对象的属性
      }
    }
  }
  
  return copy;
}

递归拷贝的实现方法如上所示。首先,判断传入的参数是否为基本数据类型或 null,如果是,则直接返回该值。接下来,根据参数的类型创建一个空的拷贝对象。

如果参数是数组,则遍历数组的每个元素,并递归调用 deepCopy 函数来拷贝每个元素。如果参数是对象,则遍历对象的属性,并递归调用 deepCopy 函数来拷贝每个属性值。

最后,返回拷贝后的对象或数组。

2. 使用JSON序列化和反序列化

另一种实现深拷贝的方法是使用JSON序列化和反序列化。这种方法适用于大多数情况,但有一些限制,例如无法拷贝特殊类型的对象(如函数、正则表达式、日期对象等)。

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

上述实现方法非常简洁。它通过先将对象或数组转换为JSON字符串,然后再将其解析回JavaScript对象来实现深拷贝。这种方法可以处理大多数情况下的深拷贝需求,但需要注意它的限制。

解决循环引用的问题

在深拷贝过程中,如果对象存在循环引用,即某个对象的属性之间形成了闭环,上述方法可能会陷入无限递归,导致堆栈溢出。为了解决这个问题,可以使用一个映射表来跟踪已经拷贝过的对象,避免重复拷贝和循环引用。

function deepCopy(obj, visited = new WeakMap()) {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // 如果是基本数据类型或 null,直接返回
  }

  if (visited.has(obj对不起,我的回答被截断了。以下是完整的代码实现:

```javascript
function deepCopy(obj, visited = new WeakMap()) {
  if (typeof obj !== 'object' || obj === null) {
    return obj; // 如果是基本数据类型或 null,直接返回
  }

  if (visited.has(obj)) {
    return visited.get(obj); // 如果已经拷贝过该对象,直接返回拷贝后的对象
  }

  let copy;

  if (Array.isArray(obj)) {
    copy = [];
    visited.set(obj, copy); // 将原始对象和拷贝对象关联起来
    for (let i = 0; i < obj.length; i++) {
      copy[i] = deepCopy(obj[i], visited); // 递归拷贝数组元素
    }
  } else {
    copy = {};
    visited.set(obj, copy); // 将原始对象和拷贝对象关联起来
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        copy[key] = deepCopy(obj[key], visited); // 递归拷贝对象的属性
      }
    }
  }

  return copy;
}

这个 deepCopy 函数使用了一个 visited 参数来跟踪已经拷贝过的对象,以处理循环引用的情况。它使用了 WeakMap 数据结构来存储原始对象和对应的拷贝对象之间的关联关系。

函数的实现方式与之前提供的方法类似,但增加了对循环引用的处理。当遇到已经拷贝过的对象时,直接返回拷贝后的对象,避免陷入无限递归。

这种实现方法可以处理大多数情况下的深拷贝需求,包括对象、数组以及嵌套的对象和数组。但需要注意的是,它仍然无法拷贝特殊类型的对象,如函数、正则表达式和日期对象。

请记住,深拷贝可能会涉及到性能方面的开销,特别是在处理大型对象或嵌套层级较深的数据时。在使用深拷贝时,请确保考虑到性能问题,并根据实际需求选择合适的实现方法。

标签:copy,obj,递归,对象,JavaScript,deepCopy,拷贝,解析
From: https://blog.51cto.com/u_16235140/7447319

相关文章

  • 无涯教程-JavaScript - TBILLPRICE函数
    描述TBILLPRICE函数返回面值$100的国库券的价格。语法TBILLPRICE(settlement,maturity,discount)争论Argument描述Required/OptionalSettlement国库券的结算日期。证券结算日期是发行国库券给买方的发行日期之后的日期。RequiredMaturity国库券的到期日。......
  • 初始JavaScript
    typora-copy-images-to:media基本语法JavaScript的历史: 在95年以前,就有很多上网的用户了,当时的带宽只有28.8kb/s,用户要进行表单的验证时,点击提交按钮,直接就将数据发送到服务器了,受限于带宽的关系,浏览器和服务器的通信很慢,大概一次通信需要30s的时间。 这样,问题就出现了,我们平常......
  • 无涯教程-JavaScript - SYD函数
    描述SYD函数返回指定期间资产的年折旧数字。语法SYD(cost,salvage,life,per)争论Argument描述Required/OptionalCostTheinitialcostoftheasset.RequiredSalvageThevalueattheendofthedepreciation(sometimescalledthesalvagevalueoftheass......
  • cmd快速拷贝文件不计算文件
    例:将a文件夹内的所有内容(包括子文件夹)复制到b文件夹xcopya*b/y/e/i/q如xcopyE:*G:\test/y/e/i/q拷贝E盘文件到G盘下的test文件夹说明:/y:不弹出“确认是否覆写已存在目标文件”的提示/e:复制文件及子文件夹内所有内容,包括空文件夹(对比/s,/s不复制空文件夹)/i:如果b......
  • JavaScript 本地时间时区变化问题
    WhatIsLocalMeanTime?由于电脑时区使用TimeZoneDatabase,所以本地时间会在1900年左右发生时区跳变,而JavaScript的Date默认遵循当前系统时区,它的构造函数要么接受一个UTC时间戳,要么接受本地时间(字符串或年月日时分秒)如果直接使用本地时间会发生以下问题:https:/......
  • Python3 XML 解析
    常见的XML编程接口有DOM和SAX,这两种接口处理XML文件的方式不同,当然使用场合也不同。Python有三种方法解析XML,SAX,DOM,以及ElementTree:1.SAX(simpleAPIforXML)Python标准库包含SAX解析器,SAX用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户......
  • Python3 JSON 数据解析
    JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。Python3中可以使用json模块来对JSON数据进行编解码,它包含了两个函数:json.dumps(): 对数据进行编码。json.loads(): 对数据进行解码。在json的编解码过程中,Python的原始类型与json类型会相互转......
  • Android项目之JSON解析(3种解析技术详解)
    一、用Android原生技术解析JSON:特点:很麻烦,对于复杂的json数据解析很容易出错!(不推荐使用)1、解析JSON对象的API:JsonObjectJSONObject(String json);将Json字符串解析成Json对象;XxxgetXxx(Stringname);根据name在json对象中得到相应的value。示例代码:(1)获取或创建JSON数据(为了方便,这里......
  • 无涯教程-JavaScript - PRICEDISC函数
    描述PRICEDISC函数返回折价证券面值$100的价格。语法PRICEDISC(settlement,maturity,discount,redemption,[basis])争论Argument描述Required/OptionalSettlement证券的结算日期。证券结算日期是指在发行日期之后将证券交易给买方的日期。RequiredMaturity......
  • 快解析内网穿透如何帮你轻松实现外网远程连接?
    外网相信大家多少了解一点,其实就是连接不同地区局域网,或者是城域网计算机通信的远程网,因此被称为广域网或者公网。在这个互联网信息时代,很多用户还是不知道怎么连接外网?外网远程桌面连接的步骤是怎样的?下文一起来了解一下。外网是什么意思?外网又被称为广域网,它可以连接极其大的物理......