js 手写深拷贝方法

news2025/2/26 18:40:42

文章目录

  • 一、深拷贝实现代码
  • 二、代码讲解
    • 2.1 obj.constructor(obj)
    • 2.2 防止循环引用

手写一个深拷贝是我们常见的面试题,在实现过程中我们需要考虑的类型很多,包括对象、数组、函数、日期等。以下就是深拷贝实现逻辑

一、深拷贝实现代码

const originalObject = {
      string: 'Hello',
      number: 42,
      boolean: true,
      array: [1, 2, 3],
      nestedObject: { key: 'value' },
      date: new Date(),
      regex: /pattern/g,
      map: new Map([['key1', 'value1'], ['key2', 'value2']]),
      set: new Set([1, 2, 3]),
      func: function (a, b) { return a + b; },
      symbol: Symbol('symbol')
  };
 
  function deepClone(obj,visited = new WeakMap()){
      
      if (visited.has(obj)) {
          // 防止循环引用
          return visited.get(obj);
      }
      
      if(typeof obj !== 'object' || obj === null){
          // 处理基本数据类型和null
          return obj
      }
      if(obj instanceof Date || obj instanceof RegExp || obj instanceof Map || obj instanceof Set){
          //处理特殊对象
          return new obj.constructor(obj)
      }
      if(Array.isArray(obj) || obj instanceof Object){
          //处理数组和对象
          const cloneObj = new obj.constructor();  
          visited.set(obj, cloneObj);
          for (let key in obj) {
              cloneObj[key] = deepClone(obj[key],visited)
          }
          return cloneObj
          
      }
      

  }
  const clonedObject = deepClone( originalObject); 
  
  console.log(clonedObject);
  console.log(originalObject)

二、代码讲解

在这里我讲解代码中我认为比较难懂的点,若大家还有什么其它不懂的地方,欢迎留言评论

2.1 obj.constructor(obj)

obj.constructor(obj) 这种写法通常用于创建一个对象的副本。针对于map,set,date,regex可以再创建一个相同但内存地址不同的的对象

 const originalObject= new Set([1, 2, 3])
 const cloneObj = new originalObject.constructor(originalObject); 
 cloneObj.add(4)
 console.log(originalObject);
 console.log(cloneObj)

在这里插入图片描述

但对于构造函数,对象,会再创建一个相同的对象(地址也相同),所以上面对于数组对象的处理我们并没有传参。

const originalObject= {
    a:1,
    b:2
}
const cloneObj = new originalObject.constructor(); 
cloneObj.c= 3
console.log(originalObject);//{a: 1, b: 2, c: 3}
console.log(cloneObj)   //{a: 1, b: 2, c: 3}

2.2 防止循环引用

在上面提供的深拷贝实现中,防止循环引用的处理主要通过使用 WeakMap 实现。WeakMap 是 ECMAScript 6 引入的一种数据结构,它允许将对象作为键存储在 Map 中,但不会阻止这些对象被垃圾回收。这使得 WeakMap 非常适合用于处理循环引用的情况。

  • 创建 visited WeakMap:参数visited = new WeakMap(),用于存储已经访问过的对象
function deepClone(obj, visited = new WeakMap()) {
  // ...
}

  • 检查是否已访问过:在处理每个对象之前,通过 visited.has(obj) 检查对象是否已经被访问过。
if (visited.has(obj)) {
  return visited.get(obj);
}

  • 将对象存储到 visited 中:在处理对象时,将其存储到 visited 中,以便后续检查循环引用。
visited.set(obj, cloneObj);

通过上面这样的处理,可以确保在深度拷贝对象的过程中,对于已经访问过的对象,直接返回其拷贝,而不会陷入无限递归的循环引用中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1477428.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

扫码看视频的效果怎么做?在电脑上制作视频活码只需3步

怎么做扫码看视频的效果呢?通过二维码来储存视频并用来做展示用途,是现在很常见的一种二维码应用类型,这种方式可以有效的提升内容的快速传播,而且用户体验也比较好。 那么如何通过视频二维码生成器的功能来制作自己的二维码图片…

提升媒体文字质量:常见错误及改进措施解析

在现代媒体出版中,文字质量直接影响着信息的传递效率和准确性。近期,中国产业报协会全国行业报质检办公室对中央及国家机关主管的84家行业报纸进行了质量检查,发现了一系列共性的文字使用错误。本文旨在深入探讨这些错误,并提出改…

Springboot中ApplicationContextInitializer的使用及源码分析

文章目录 一、认识ApplicationContextInitializer1、ApplicationContextInitializer的作用2、认识ApplicationContextInitializer接口3、ApplicationContextInitializer的常用用法(1)注册BeanFactoryPostProcessor(2)注册Applicat…

关于StartAI本地部署相关问题解答

很多小伙伴们都有接入自己本地SD的需求,对此小编整理了一些相关问题~ 一、本地部署相关条件 对于想要本地部署的小伙伴要了解,相对于使用StartAI试用引擎本地部署更加考验电脑硬件配置备噢~ 流畅使用要nvidia显卡,6g以上显存(最…

Google发布Genie硬杠Sora:通过大量无监督视频训练最终生成可交互虚拟世界

前言 Sora 问世才不到两个星期,谷歌的世界模型也来了,能力看似更强大(嗯,看似):它生成的虚拟世界自主可控 第一部分 首个基础世界模型Genie 1.1 Genie是什么 Genie是第一个以无监督方式从未标记的互联网视频中训练的生成式交互…

浅析前端的堆栈原理以及深浅拷贝原理

浅析前端的堆栈原理以及深浅拷贝原理 首先来看一个案例 const obj {name:hzw,age:18 } let objName2 obj objName2.age 12 console.log(obj,objName2) // {name: hzw, age: 12} {name: hzw, age: 12}这里是不是很奇怪,为什么,为什么我改变objName2的…

使用 Gradle 版本目录进行依赖管理 - Android

/ 前言 / 在软件开发中,依赖管理是一个至关重要的方面。合理的依赖版本控制有助于确保项目的稳定性、安全性和可维护性。 Gradle版本目录(Version Catalogs)是 Gradle 构建工具的一个强大功能,它为项目提供了一种集中管理依赖…

轻松玩转Git

轻松玩转Git 快速入门什么是Git为什么要做版本控制安装git Git实战单枪匹马开始干拓展新功能小结 紧急修复bug分支紧急修复bug方案命令总结工作流 上传GitHub第一天上班前在家上传代码初次在公司新电脑下载代码下班回到家继续写代码到公司继续开发在公司约妹子忘记提交代码回家…

算法——滑动窗口之最大连续1的个数、将x减到0的最小操作数、水果成篮

3.最大连续1的个数 题目:. - 力扣(LeetCode) 题目要求的是给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。 按照题目正面去做,还要替换0,很麻烦 反正我们最后要求的是最长…

算法C++

枚举 1.化段为点 前缀和 eg:给一个数列&#xff0c;算x到y个数的和 #include <iostream> #include <vector> using namespace std;int main() {int n;cin>>n;vector<int> a(n);vector<int> sum(n1,0);for(int i0;i<n;i){scanf…

三种食物轮流吃,睡眠时间又长又香!

睡眠质量一直是人们关注的焦点&#xff0c;而饮食则被认为是影响睡眠的重要因素之一。近年来&#xff0c;有一种食物搭配方法备受瞩目&#xff0c;据说可以让人们的睡眠时间又长又香。这种方法并不复杂&#xff0c;只需要轮流食用三种特定食物&#xff0c;就能有效改善睡眠质量…

好用的AI模型集合

AI-Chat 这个网站提供的AI-Chat 3.5和AI-Chat 4.0聊天机器人&#xff0c;每天都可以免费使用。 不管是学习、工作还是日常生活&#xff0c;都能给我们带来很大的帮助&#xff0c;效率真的可以说是翻倍了。我觉得&#xff0c;如果你想让自己的生活更加高效、更加有序&#xff0…

Groovy - 大数据共享搜索配置

数据共享搜索列中配置了搜索列&#xff0c;相应的数据共享接口中也需要支持根据配置的字段搜索&#xff0c;配置实体时&#xff0c;支持搜索的入参code必须是searchKeys&#xff0c;且接口应该是需要支持分页&#xff08;入参必须是 current、pageSize&#xff09;的。current …

如何利用IP代理高效采集产品数据,打造爆品?

文章目录 一、什么是网络爬虫&#xff1f;二、普通人如何通过网络爬虫赚钱&#xff1f;2.1、心得分享2.2、工具自动化收集信息 三、 动态IP代理3.1、覆盖范围3.2、性价比3.3、教程中心F&Q使用教程 3.4、在网络数据采集中的重要性 四、实战应用案例一&#xff1a;ebay电商【…

树莓派驱动编译

驱动编译前提&#xff1a;驱动代码的编译需要提前编译号的内核 驱动&#xff08;3种实现方法&#xff0c;2条路线&#xff09;_驱动编写三种方法-CSDN博客 驱动的编写_驱动编写-CSDN博客 一、概念 1.1、驱动认识 1、裸机程序中是直接操控硬件的&#xff0c;操作系统…

【论文笔记】Attention Is All You Need

【论文笔记】Attention Is All You Need 文章目录 【论文笔记】Attention Is All You NeedAbstract1 Introduction2 Background补充知识&#xff1a;软注意力 soft attention 和硬注意力 hard attention&#xff1f;补充知识&#xff1a;加法注意力机制和点乘注意力机制Extende…

JavaScript的书写方式

JavaScript的书写方式 目前较为流行的是第二种和第三种&#xff0c;第一种很少见。在第二种和第三种推荐使用第三种&#xff0c;因为在日常开发/工作中&#xff0c;第三种是最为常见的 1.行内式 把JS代码嵌入到html元素内部 示例代码 运行效果 由于JS中字符串常量可以使用单引…

如何让电脑待机而wifi不关的操作方法!!

1、一台电脑如果一天不关机&#xff0c;大约消耗0.3度电。 一般一台电脑的功耗约为250-400W&#xff08;台式机&#xff09;。 一台电脑每月的耗电量&#xff1a;如果是每小时300W每天10小时每月30天90KW&#xff0c;即90千瓦时的电。 这只是保守估计。 2、使用完毕后正常关闭…

微调(Fine-tuning)技术概念

——微调&#xff0c;像化妆&#xff0c;一种“精细化、风格性调整”的人工美颜技能。 微调&#xff08;Fine-tuning&#xff09;是指在深度学习领域中&#xff0c;特别是针对预训练模型的一种训练策略。预先训练好的模型通常是在大规模无标注数据上通过自监督学习得到的&#…

Python股票数据,指数月线涨跌幅回测系统

1.这是我用Python写的&#xff0c;目前无法给大家直接使用exe&#xff0c;因为编译后软件不能正常使用。但是py源码可以先开源&#xff0c;给大家学习一下&#xff0c;里面的代码&#xff0c;都有我的注释&#xff0c;需要你有编程基础就可以看懂&#xff0c;自己可以在这个基础…