深度拷贝 deepClone

/**
 * 深度克隆对象
 * @param {*} value 需要克隆的值 
 * @param {WeakMap} cache 使用 WeakMap 解决环形引用问题,防止内存泄漏 
 */
function deepClone(value, cache = new WeakMap()) {
    // 基础数据
    if(typeof value !== 'object' || value === null) {
        return value;
    }
    // 解决环形引用问题
    if(cache.has(value)) {
        return cache.get(value);
    }
    const toString = Object.prototype.toString.call(value).slice(8,-1);
    if(toString === 'Date') { // 日期时间
        const result = new Date();
        Object.setPrototypeOf(result, Object.getPrototypeOf(value));
        return result;
    } else if(toString === 'Map' || toString === 'Set') { // 集合类型
        const result = toString === 'Map'? new Map() : new Set();
        Object.setPrototypeOf(result, Object.getPrototypeOf(value));
        value.forEach(function(item, key) {
            let nkey, nval;
            if(typeof key === 'object' && key !== null) {
                nkey = deepClone(key, cache)
                cache.set(key, nkey)
            } else {
                nkey = key
            }
            if(typeof item === 'object' && item !== null) {
                nval = deepClone(item, cache)
                cache.set(item, nval)
            } else {
                nval = item
            }
            toString === 'Map' ? this.set(nkey, nval) : this.add(nval)
        }, result)
        return result;
    } else {
        // 克隆结果 1.数组 2.对象
        const result = Array.isArray(value) ? [] : {};
        // 设置克隆结果的原型链为 value 的原型链(即保持原型一致)
        Object.setPrototypeOf(result, Object.getPrototypeOf(value));
        // 环形引用时将克隆的值储存到缓存中
        cache.set(value, result)
        for(const key in value) {
            // 排除原型上的属性
            if (Object.prototype.hasOwnProperty.call(value, key)) {
                if(typeof value[key] === 'object' && value[key] !== null) {
                    result[key] = deepClone(value[key], cache)
                } else {
                    result[key] =  value[key]
                }
            }
        }
        return result;
    }
}

测试例子

var date = new Date()
var dated2 = deepClone(date)
date.setFullYear(2015)
dated2.setFullYear(2018)
console.log(date);
console.log(dated2);

var map1 = new Map();
map1.set('name', '小明')
var foo = {age:18}
map1.set(foo, {nation:'汉族'})
map1.set('bar', {a:'abc'})
var map2 = deepClone(map1)

map1.set('name','张三')
var bar = map1.get('bar')
bar.a = 'def'
foo.age = 22
map1.set('bar', bar)

var foo2 = map1.get(foo)
foo2.nation = "中国"

map2.set('name','李四')
console.log(map1);
console.log(map2);

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Enterprise Architect 12版本使用教程

Enterprise Architect 12版本使用教程 1.下载安装Enterprise Architect 122.Enterprise Architect原始DDL模板配置及存在的问题1.DDL Column Definition原始模板(没有default值:可忽略)2.DDL Data Type原始模板(timestamp等时间字…

BCrypt加密解密工具类方法

BCrypt加密解密工具类方法 直接上代码 package com.loit.park.common.utils;import org.springframework.security.crypto.bcrypt.BCrypt;/*** author hanjinqun* date 2023/5/13* BCrypt工具类*/ public class BCryptUtils {/*** 加密*/public static String hashpw(String s…

【JavaEE进阶】 Spring使用注解存储对象

文章目录 🌴序言🍀前置⼯作:配置扫描路径🎄添加注解存储 Bean 对象🌳类注解🚩为什么要这么多类注解🚩注解之间的联系 🎋⽅法注解 Bean🚩⽅法注解需要配合类注解使⽤ ⭕总…

C //习题10.8 将第7题结果仍存入原有的“stu_sort“文件而不另建立新文件。

C程序设计 (第四版) 谭浩强 习题10.8 习题10.8 将第7题结果仍存入原有的"stu_sort"文件而不另建立新文件。 IDE工具:VS2010 Note: 使用不同的IDE工具可能有部分差异。 说明:此题同习题10.7的代码,唯一的区…

大数据毕业设计之前端03:logo、menu的折叠展开实现

关键字:BuildAdmin、pinia、logo、aside、menu、菜单折叠、Vue、ElementUI 前言 上一篇文章中,借助aside的实现讲了一些开发的小技巧,以及css的解读。本篇文章主要写一下如何填充aside的内容。 aside主要是由两个部分组成的:log…

Mysql启动占用内存过高解决

Hi, I’m Shendi Mysql启动占用内存过高解决 前言 最近服务器内存不够用了,甚至还出现了内存溢出问题,导致程序宕机。但请求与用户量并没有多少,所以从各种启动的程序中想方设法的尽可能的减少其占用的内存。 而在我的服务器中,…

数字化和数智化一字之差,究竟有何异同点?

在2023杭州云栖大会的一展台内,桌子上放着一颗番茄和一个蛋糕,一旁的机器人手臂融入“通义千问”大模型技术后,变得会“思考”:不仅能描述“看”到了什么,还能确认抓取的是番茄而不是蛋糕。 “传统的机械臂通常都只能基…

从0到1,手把手带你开发截图工具ScreenCap------001实现基本的截图功能

ScreenCap---Version:001 说明 从0到1,手把手带你开发windows端的截屏软件ScreenCap 当前版本:ScreenCap---001 支持全屏截图 支持鼠标拖动截图区域 支持拖拽截图 支持保存全屏截图 支持另存截图到其他位置 GitHub 仓库master下的Scr…

二百一十四、Linux——Linux系统时间比电脑时间慢5分钟

一、目的 服务器重启后,发现Linux的系统时间比电脑时间慢5分钟,于是看了些博客,终于找到了解决方法,记录一下,以防止后面出现同样的问题 二、问题 通过date查看,Linux系统时间比电脑时间慢5分钟 &#…

solidworks打开图纸零件隐藏看不到怎么办?

solidworks打开图纸零件隐藏看不到怎么办?solidworks打开时看不到零件图像,显示空白文档,该怎么解决这个问题呢?下面我们就来看看详细的教程,需要的朋友可以参考下 1、打开SolidWorks ,并选中需要打开的零…

【公式】逻辑回归的损失函数是什么

目录 一、逻辑回归简介 二、逻辑回归模型的损失函数 2.1 损失函数与其意义 2.2 逻辑回归的损失函数 2.3 从交叉熵角度理解逻辑回归的损失函数 2.4 从对数似然角度推导逻辑回归的损失函数 三、逻辑回归损失函数的梯度 3.1 逻辑回归损失函数的梯度公式 3.2 用梯度下降法…

家用洗地机希亦、追觅和添可哪款好用?测评PK谁是清洁之王

对于上班族来说,时间非常宝贵,打扫卫生就成为了一件比较痛苦的事情。现在的都市上班族都会寄托于智能家电。在当前市场上,洗地机已成为家庭清洁的面部工具。洗地机是一种高效的清洁设备,以其自动化、高效率的清洁功能,…

我想涨工资,请问测试开发该怎么入门?

我是测试开发工程师!欢迎和我交流测试领域相关问题(测试入门、技术、python交流都可以) 我几乎是靠这套方法,从一个只会功能测试的小白,到成为测试开发工程师的。 别急,先慢慢看,只要按照下面的流程走一遍…

Elastic Support Hub 转向语义搜索

作者:Chris Blaisure 我们很高兴与大家分享 Elastic Support Hub 最近的增强功能:它现在由语义搜索提供支持! 但在我们更详细地了解对 Elastic Support Hub 所做的更改及其对客户的影响之前,我们需要花点时间解释语义搜索的概念&…

java死锁的成因和解决方案

一、什么是死锁? 在Java中,死锁是指两个或多个线程互相持有对方所需要的锁,并且在无法继续执行的情况下永久地等待对方释放锁。这种情况下,所有涉及的线程都无法继续执行,程序被卡住,无法正常终止。 死锁通…

Question 1----dlib问题

复现代码时,在环境里边导入dlib包时一直出现setup.py运行失败,查找网上一些解决方法,使用whl文件本地导入 仍然不能解决,通过向师兄请教,成功解决问题。 首先需要先安装两个库:(已经安装好了VS…

pyside/qt03——人机协同的编程教学—直接面向chatGPT实战开发(做中学,事上练)

先大概有个草图框架,一点点丰富 我纠结好久,直接用Python写UI代码 还是用designer做UI 再转Python呢, 因为不管怎么样都要转成Python代码, 想了想还是学一下designer吧,有个中介,有直观理解。 直接这样也可…

“福利”还是“陷阱”?公司给员工放假3个月引发劳动权益争议

近日,广东佛山一家玻璃制造公司的长达3个月放假通知引发广泛关注。这一决策引发了社会对员工福利和公司经营平衡的深入思考。公司表示,此次决策是为了维修老化设备,但随之而来的疑虑则主要集中在员工的收入和劳动权益问题上。 公司表示&…

Java线程池—附阿里巴巴Java开发手册强制规范要求

文章目录 一、线程池概述二、创建线程池三、线程池执行Runnable任务四、线程池执行Callable任务五、线程池工具类(Executors)—不推荐 一、线程池概述 线程池就是一个可以复用线程的技术。 想象一下,如果不使用线程池会有什么问题&#xff1…

spring IOC介绍

spring的Ioc真是个好东西啊,那它到底是什么东西呢,控制反转,到底是怎么转的呢? 假设啊你现在是一个导演,想排部戏,那是不是得需要演员和舞台(spring中的bean),如果按平常的编程思维就是new 一个…