实现 js 中所有对象的深拷贝(包装对象,Date 对象,正则对象)

通过递归可以简单实现对象的深拷贝,但是这种方法不管是 ES6 还是 ES5 实现,都有同样的缺陷,就是只能实现特定的 object 的深度复制(比如数组和函数),不能实现包装对象 Number,String , Boolean,以及 Date 对象,RegExp 对象的复制。

(1)简单的深拷贝

function deepClone(obj) {var newObj = obj instanceof Array ? [] : {}for (var i in obj) {newObj[i] = typeof obj[i] == 'object' ? deepClone(obj[i]) : obj[i]}return newObj
}


这种方法可以实现一般对象和数组对象的拷贝,比如:

var arr = [1, 2, 3]var newArr = deepClone(arr)// newArr->[1,2,3]var obj = {x: 1,y: 2
}var newObj = deepClone(obj)// newObj={x:1,y:2}


但是不能实现例如包装对象 Number,String,Boolean,以及正则对象 RegExp 和 Date 对象的拷贝,比如:

//Number 包装对象var num = new Number(1)typeof num // "object"var newNum = deepClone(num)//newNum -> {} 空对象//String 包装对象var str = new String('hello')typeof str //"object"var newStr = deepClone(str)//newStr-> {0:'h',1:'e',2:'l',3:'l',4:'o'};//Boolean 包装对象var bol = new Boolean(true)typeof bol //"object"var newBol = deepClone(bol)// newBol ->{} 空对象


(2)valueof()函数

所有对象都有 valueOf 方法,valueOf 方法对于:如果存在任意原始值,它就默认将对象转换为表示它的原始值。对象是复合值,而且大多数对象无法真正表示为一个原始值, 因此默认的 valueOf()方法简单地返回对象本身,而不是返回一个原始值。数组、函数和正则表达式简单地继承了这个默认方法,调用这些类型的实例的 valueOf()方法只是简单返回这个对象本身。

对于原始值或者包装类:

function baseClone(base) {return base.valueOf()
}//Numbervar num = new Number(1)var newNum = baseClone(num)//newNum->1//Stringvar str = new String('hello')var newStr = baseClone(str)// newStr->"hello"//Booleanvar bol = new Boolean(true)var newBol = baseClone(bol)//newBol-> true


其实对于包装类,完全可以用=号来进行拷贝,其实没有深拷贝一说,这里用 valueOf 实现,语法上比较符合规范。

对于 Date 类型:

因为 valueOf 方法,日期类定义的 valueOf()方法会返回它的一个内部表示:1970 年 1 月 1 日以来的毫秒数.因此我们可以在 Date 的原型上定义拷贝的方法:

Date.prototype.clone = function () {return new Date(this.valueOf())
}var date = new Date('2010')var newDate = date.clone()// newDate-> Fri Jan 01 2010 08:00:00 GMT+0800
对于正则对象 RegExp:RegExp.prototype.clone = function () {var pattern = this.valueOf()var flags = ''flags += pattern.global ? 'g' : ''flags += pattern.ignoreCase ? 'i' : ''flags += pattern.multiline ? 'm' : ''return new RegExp(pattern.source, flags)
}var reg = new RegExp('/111/')var newReg = reg.clone()//newReg-> /\/111\//


最终解决方案:

// 在深拷贝的基础上,对(包装对象Number,String,Boolean;Date 对象,RegExp正则对象)进行深拷贝

function deepClone(obj) {let newObj = obj instanceof Array ? [] : {}for (let i in obj) {// for...in 会遍历原型上的属性,此处只拷贝obj对象自身的属性if (obj.hasOwnProperty(i)) {let type = Object.prototype.toString.call(obj[i])if (typeof obj[i] == 'object') {// 拷贝的值为对象,则需要深拷贝if (type == '[object Date]') {newObj[i] = new Date(obj[i].valueOf())} else if (type == '[object RegExp]') {// 正则对象let pattern = obj[i].valueOf()let flags = ''flags += pattern.global ? 'g' : ''flags += pattern.ignoreCase ? 'i' : ''flags += pattern.multiline ? 'm' : ''newObj[i] = new RegExp(pattern.source, flags)} else if (type == '[object Array]' || type == '[object Object]') {// 数组或对象newObj[i] = deepClone(obj[i])} else {// 包装对象Number,String,BooleannewObj[i] = obj[i].valueOf()}} else if (typeof obj[i] == 'function') {// 函数newObj[i] = new Function('return ' + obj[i].toString())()} else {// 拷贝的值为原始值,则直接复制该值newObj[i] = obj[i]}}}return newObj
}


测试:


let obj = {name: 'zs',age: 20,food: ['apple', 'banana', 'orange'],obj1: {school: 'nyist'},reg: new RegExp('/A-Z/', 'gi'),date: new Date(),bol: new Boolean(true),num: new Number(999),fn: function () {this.age++}
}let res = deepClone(obj)res.obj1.school = '清华'
res.fn = function (a, b) {console.log(a, b)
}
res.food[1] = '香蕉'console.log('res', res, 'obj', obj)
console.log(res.reg === obj.reg)

原文链接:https://blog.csdn.net/weixin_52624519/article/details/129265211

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

180B参数的Falcon登顶Hugging Face,vs chatGPT 最好开源大模型使用体验

文章目录 使用地址使用体验test1:简单喜好类问题test2:知识性问题test3:开放性问题test4:中文支持test5:问题时效性test6:学术问题使用地址 https://huggingface.co/spaces/tiiuae/falcon-180b-demo 使用体验 相比Falcon-7b,Falcon-180b拥有1800亿的参数量

【Axure高保真原型】日历日期原型模板

今天和大家分享日历日期的原型模板,包括月计划、周计划、日计划的原型案例,以及日期、时间、月份、区间选择器……具体效果可以点击下方视频观看 【原型预览及下载地址】 Axure 原型 备用地址:Untitled Document 【原型效果】 【原型效果…

Unity技术手册-UGUI零基础详细教程-Canvas详解

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 👉关于作者 专注于Android/Unity和各种游…

【Unity】Unity坑的集锦之RenderTexture打包黑屏

问题:Camera Output Texture设置RenderTexture后,打包用来Save PNG,黑屏 如果你打AB 包,然后是相机的OutputTexture是拖拽的话,记得将包一起打入 或者你可以代码赋值 Camera.targetTexture await Loader.LoadAsset&l…

【算法系列 | 8】深入解析查找算法之—二分查找

序言 心若有阳光,你便会看见这个世界有那么多美好值得期待和向往。 决定开一个算法专栏,希望能帮助大家很好的了解算法。主要深入解析每个算法,从概念到示例。 我们一起努力,成为更好的自己! 今天第8讲,讲一…

IO day7

1->x.mind 2-> A进程 B进程

[Google DeepMind] LARGE LANGUAGE MODELS AS OPTIMIZERS

Large Language Models as Optimizers 文章链接 总体架构Optimization by PROmpting (OPRO):最开始输入meta-prompt,这个初始的meta-prompt基本上只是对优化任务进行了描述(也会有few-shot example)。输入后LLM便会生成一个solution,这个sol…

Vue3:proxy数据取值proxy[Target]取值

vue3底层是使用proxy进行代理的&#xff0c;而proxy中[[Target]]才是想要的值。 获取target值的方式一&#xff1a; <script setup>//先引入toRawimport { toRaw } from vue;//再使用console.log(toRaw(数据名))</script> 获取target值的方式二&#xff1a; <…

NIO基础

一、NIO基础 Java New IO是从Java1.4版本开始引入的一个新的IO api&#xff0c;可以替代以往的标准IO&#xff0c;NIO相比原来的IO有同样的作用和目的&#xff0c;但是使用的方式完全不一样&#xff0c;NIO是面向缓冲区的&#xff0c;基于通道的IO操作&#xff0c;这也让它比传…

Java学习之--类和对象

&#x1f495;粗缯大布裹生涯&#xff0c;腹有诗书气自华&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;Java学习之--类和对象 类和对象 类的实例化&#xff1a; 1.什么叫做类的实例化 利用类创建一个具体的对象就叫做类的实例化&#xff01; 当我们创建了…

Vulnhub系列靶机---HarryPotter-Fawkes-哈利波特系列靶机-3

文章目录 信息收集主机发现端口扫描dirsearch扫描gobuster扫描 漏洞利用缓冲区溢出edb-debugger工具msf-pattern工具 docker容器内提权tcpdump流量分析容器外- sudo漏洞提权 靶机文档&#xff1a;HarryPotter: Fawkes 下载地址&#xff1a;Download (Mirror) 难易程度&#xff…

工厂除静电除尘设备--离子风枪

静电无处不在&#xff0c;区别在于静电的多少而已。特别是工业生产过程中&#xff0c;大量的静电会有很多危害。 静电的危害有几点&#xff1a;1.引起电子设备的故障或误动作&#xff0c;造成电磁干扰。2.击穿集成电路和精密的电子元件&#xff0c;或使元件老化&#xff0c;拉…

关于一个left join的易错点

很多人在学习mysql的时候应该都出现过很多问题&#xff0c;特别是连接方面的问题应该最多&#xff0c;希望这篇文章帮助到正在找bug的你 Java报错数据返回数量出现错误 遇到这种问题一定要看日志 很明显通过left join查询除了两条数据并且为空 马上思考错误的原因&#xff0c;…

【Java基础篇 | 面向对象】--- 聊聊什么是多态(上篇)

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【JavaSE_primary】 本专栏旨在分享学习JavaSE的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、什么是多态二、多…

数据结构基础7:二叉树【链式结构】实现和递归思想。

二叉树的链式结构实现 一.二叉树链式结构的实现&#xff1a;1.前置说明&#xff1a;1.创建二叉树&#xff1a;2.二叉树的结构&#xff1a; 2.二叉树的遍历&#xff1a;1.二叉树的前中后序遍历&#xff1a;2.内容拓展&#xff1a; 二.二叉树链式(题目)题目一&#xff1a;计算节点…

小程序源码:多功能口袋工具箱微信小程序源码-带流量主|云开发(更新)

这里主要分享多功能口袋工具箱微信小程序源码&#xff0c;有带流量主&#xff0c;而且超多功能工具箱组合的微信小程序源码。无需服务器即可搭建&#xff0c;可以设置流量主赚取收益。 源码链接&#xff1a; 网盘源码 密码&#xff1a;hma8 工具箱的应用一览&#xff1a; 1…

【计算机网络】传输层协议——TCP(上)

文章目录 TCPTCP协议段格式报头和有效载荷如何分离&#xff1f;4位首部长度 TCP可靠性确认应答机制的提出序号和确认序号为什么序号和确认序号在不同的字段&#xff1f; 16位窗口大小 6个标志位标志位本质具体标志位PSHRSTURG 超时重传机制 文章目录 TCPTCP协议段格式报头和有效…

Qt Designer UI设计布局小结

目录 前言1 居中布局2 左右布局3 上下布局4 复杂页面布局总结 前言 本文总结了在开发Qt应用程序时使用 Designer 进行UI布局的一些心得体会。Qt Designer是Qt提供的一个可视化界面设计工具&#xff0c;旨在帮助开发人员快速创建和布局用户界面。它提供了丰富的布局管理器和控件…

我的个人网站——宏夏Coding上线啦

网站地址&#xff1a;宏夏Coding Github地址&#xff1a;&#x1f525;&#x1f525;宏夏coding网站&#xff0c;致力于为编程学习者、互联网求职者提供最需要的内容&#xff01;网站内容包括求职秘籍&#xff0c;葵花宝典&#xff08;学习笔记&#xff09;&#xff0c;资源推…

线性代数的学习和整理20,关于向量/矩阵和正交相关,相似矩阵等(草稿)

目录 1 什么是正交 1.1 正交相关名词 1.2 正交的定义 1.3 正交向量 1.4 正交基 1.5 正交矩阵的特点 1.6 正交矩阵的用处 1 什么是正交 1.1 正交相关名词 orthogonal set 正交向量组正交变换orthogonal matrix 正交矩阵orthogonal basis 正交基orthogonal decompositio…