实现 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
相关文章:
实现 js 中所有对象的深拷贝(包装对象,Date 对象,正则对象)
通过递归可以简单实现对象的深拷贝,但是这种方法不管是 ES6 还是 ES5 实现,都有同样的缺陷,就是只能实现特定的 object 的深度复制(比如数组和函数),不能实现包装对象 Number,String ࿰…...
PathVariable注解
postman测试传参:http://localhost:8080/admin/employee/2 PathVariable PathVariable注解用法和作用...
宋浩高等数学笔记(十二)无穷级数
完结,宋浩笔记系列的最后一更~ 之后会出一些武忠祥老师的错题&笔记总结,10月份就要赶紧做真题了...
使用Clipboard插件实现Vue的剪贴板功能
在Web开发中,剪贴板功能是一个常见但又非常有用的功能。通过将数据复制到剪贴板,用户可以方便地将数据粘贴到其他应用程序或网站上。在本文中,我们将介绍如何使用Clipboard插件结合Vue框架实现剪贴板功能。 Clipboard插件简介 Clipboard插件…...
Latex参考文献中大写字母编译后自动变成了小写,如何保持原字母大写形式
一、问题 1.1 bib文件原有内容 以下参考文献中MANET为大写 inproceedings{Miao2013FullySK, title{Fully Self-organized Key Management Scheme in MANET and Its Applications}, author{Fuyou Miao and Wenjing Ruan and Xianchang Du and Suwan Wang}, year{2013} } …...
Jest单元测试相关
官方文档:jest 中文文档 1、模拟某个函数,并返回指定的结果 使用Jest测试JavaScript(Mock篇) 有这样一个需求,mock掉Math.random方法(0(包括)~1之间),使其返回指定的0…...
Scrum敏捷开发流程及关键环节
Scrum是一种敏捷开发流程,它旨在使软件开发更加高效和灵活。Scrum将软件开发过程分为多个短期、可重复的阶段,称为“Sprint”。每个Sprint通常为两周,旨在完成一部分开发任务。 在Scrum中,有一个明确的角色分工: 产…...
微服务04-Gateway网关
作用 身份认证:用户能不能访问 服务路由:用户访问到那个服务中去 负载均衡:一个服务可能有多个实例,甚至集群,负载均衡就是你的请求到哪一个实例上去 请求限流功能:对请求进行流量限制,对服务…...
YOLOV7改进-针对小目标的NWD(损失函数)
link 1、复制这些 2、utils-loss,这里加 3、把这几行复制到utiils的loss.py 4、先对CoputerLoss类做修改 5、把那一行替换成这个 6、修改 7、iou_ration是超参,可以调,如果小目标比较多的话,这个值可以低一些,…...
计算机二级考试题库及答案
题目一:计算机网络基础 1.计算机网络的定义是什么? 计算机网络是指由通讯设备和不同类型计算机组成的计算机系统,利用传输介质,如电缆、光缆、无线等与通讯协议,实现计算机之间的信息传递和共享资源。 2. 内网和外网有什么区别…...
2023国赛高教社杯数学建模C题思路分析
1 赛题 在生鲜商超中,一般蔬菜类商品的保鲜期都比较短,且品相随销售时间的增加而变差, 大部分品种如当日未售出,隔日就无法再售。因此, 商超通常会根据各商品的历史销售和需 求情况每天进行补货。 由于商超销售的蔬菜…...
Ansible playbook简介与初步实战,实现批量机器应用下载与安装
一.Ansible playbook简介 playbook是ansible用于配置,部署,和管理被节点的剧本通过playbook的详细描述,执行其中的一些列tasks,可以让远端的主机达到预期的状态。playbook就像ansible控制器给被控节点列出的一系列to-do-list&…...
[machine Learning]强化学习
强化学习和前面提到的几种预测模型都不一样,reinforcement learning更多时候使用在控制一些东西上,在算法的本质上很接近我们曾经学过的DFS求最短路径. 强化学习经常用在一些游戏ai的训练,以及一些比如火星登陆器,月球登陆器等等工程领域,强化学习的内容很简单,本质就是获取状…...
09-JVM垃圾收集底层算法实现
上一篇:08-JVM垃圾收集器详解 1.三色标记 在并发标记的过程中,因为标记期间应用线程还在继续跑,对象间的引用可能发生变化,多标和漏标的情况就有可能发生。 这里我们引入“三色标记”来给大家解释下,把Gcroots可达…...
系统软件启动过程
实验一:系统软件启动过程 参考 重要文件 调用顺序 1. boot/bootasm.S | bootasm.asm(修改了名字,以便于彩色显示)a. 开启A20 16位地址线 实现 20位地址访问 芯片版本兼容通过写 键盘控制器8042 的 64h端口 与 60h端口。b.…...
【自学笔记】Python中的逻辑函数:any()、all()及同类函数的用法与示例
文章目录 Python中的逻辑函数:any()、all()及其他any()函数使用示例all()函数使用示例其他同类函数Python中的逻辑函数:any()、all()及其他 在Python中,any()和all()是两种常用的逻辑函数,它们在处理布尔值(True或False)的集合时非常有用。除此之外,Python还提供了一些其…...
OpenCV的绘图函数,实力绘画篮球场
关键函数:cv2.line(),cv2.circle(),cv2.rectangle(),cv2.ellipse(),cv2.putText() 等。 绘制几何形状 import cv2 as cv import numpy as npcv.rectangle(),cv.circle(),cv.line(),…...
Java之包装类的算法小题的练习
算法小题 练习一: 需求: 键盘录入一些1~10日之间的整数,并添加到集合中。直到集合中所有数据和超过200为止。 代码示例: public class Test1 {public static void main(String[] args) {/*键盘录入一些1~10日之间的整数&…...
干涉阵相关知识
文章目录 Dirty ImageDirty BeamClean ImagePoint Spread Function(PSF)Station Beam关系Dirty Image 脏图像(Dirty Image): 脏图像是在射电干涉测量中观测到的图像,它是真实图像和仪器效应(包括PSF和站波束)的组合结果。 在射电干涉测量中,观测到的结果被称为“脏图像…...
如何使用Python进行可视化/音视频处理?
要使用Python进行可视化和音视频处理,可以使用以下库: matplotlib:用于绘制各种类型的图表和图形,包括折线图、柱状图、散点图等。 seaborn:基于matplotlib的可视化库,提供更高级别的图表和样式࿰…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...
内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献
Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译: ### 胃肠道癌症的发病率呈上升趋势,且有年轻化倾向(Bray等人,2018&#x…...
前端工具库lodash与lodash-es区别详解
lodash 和 lodash-es 是同一工具库的两个不同版本,核心功能完全一致,主要区别在于模块化格式和优化方式,适合不同的开发环境。以下是详细对比: 1. 模块化格式 lodash 使用 CommonJS 模块格式(require/module.exports&a…...
五、jmeter脚本参数化
目录 1、脚本参数化 1.1 用户定义的变量 1.1.1 添加及引用方式 1.1.2 测试得出用户定义变量的特点 1.2 用户参数 1.2.1 概念 1.2.2 位置不同效果不同 1.2.3、用户参数的勾选框 - 每次迭代更新一次 总结用户定义的变量、用户参数 1.3 csv数据文件参数化 1、脚本参数化 …...
