JS :深拷贝解析与实现(附structuredClone语法测试)

浅拷贝简介

深拷贝是创建一个新对象,这个新对象包含原对象所有属性的全新拷贝,无论是基本数据类型还是引用类型的数据都会被完全复制一份,新旧对象间不存在任何关联,彼此独立。

前言

OK,最近又又又在学习JS的过程中遇到了有意思的问题,就是如何对一个复杂类型也就是对象类型实现深拷贝,浅拷贝大家都会,直接创建变量赋值就行,可是深拷贝呢?
我想到用for in 语法遍历对象属性,然后对新对象进行赋值 。


function shallowCopy(obj) {
    let newObj = {};
    for (let key in obj) {
        // key是不是obj显示具有的属性
        if (obj.hasOwnProperty(key)) {
                newObj[key] = obj[key];
        }
    }
    return newObj;
}


ok,问题是如果出现下面这种情况则无法满足,因为obj的子元素person任然是对象类型,直接赋值传进来的是地址,就不满足深拷贝了。那么接下来我们就要展开来详细谈论一下深拷贝。

var obj = {
    person:{
        name :'柳如烟',
        age: 18
    }
}

深拷贝实现方式

以下是我所知道的深拷贝方式

  • JSON.parse(JSON.stringify(obj))
  • structuredClone
  • 手写deepClone

    接下来我将分别通过相同的测试集来讲述一下他们的限制与功能。
let obj = {
    a: 1,
    b: { n: 2 },
    c: 'cc',
    d: true,
    e: undefined,
    f: null,
    g: function () { },
    h: Symbol(1),
    i: 123n,
    j: [1, 2, 3, 4]
}

JSON.parse(JSON.stringify(obj))

JSON.parse(JSON.stringify(obj)) 是JavaScript中实现深拷贝的一种简便方法,这种用法源自于JavaScript语言本身对JSON对象的支持以及这两个方法的特性。

  • JSON.stringify: 这个方法用于将JavaScript对象转换成JSON字符串。它能够序列化JavaScript对象,包括对象字面量、数组等,将其转换为字符串格式,以便于存储或在网络上传输。

  • JSON.parse: 则是JSON.stringify的逆操作,用于将JSON格式的字符串解析回JavaScript值(通常是对象或数组)。这个过程称为反序列化。

代码实现
let newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj);
测试结果

image.png
bigInt类型不能加入测试集否则会直接报错,我们可以发现,undefined、function、Symbol都是无法进行Clone

structuredClone(obj)

structuredClone 是一个相对较新的JavaScript原生函数,用于创建一个对象或值的深拷贝。该方法在 ECMAScript 2021(ES12)规范中被引入,相较于传统的JSON.parse(JSON.stringify(obj))方法,它具有更多的优势和更广泛的适用性。

代码实现
const newObj = structuredClone(obj);
console.log(newObj);
测试结果

image.png

这里的functionSymbol类型都不能进行深拷贝,因为该语法不支持functionSymbol类型的深拷贝。事实上,structuredClone支持更多JSON无法进行clone的数据类型这里就不一一展开讨论,structuredClone功能是要比JSON更加强大,但是因为是新的语法所以兼容性是稍逊一筹。

自定义深拷贝

递归思想

自定义深拷贝通常通过递归遍历对象的所有属性,对于基本类型直接复制,而对于引用类型则继续递归调用深拷贝函数,确保完全独立地复制所有层级的数据结构。

代码实现
function shallowCopy(obj) {
    let newObj = {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            // 判断一下obj[key]是不是一个对象
            if (obj[key] instanceof Object) {
            //如果是对象则进行递归操作
                newObj[key] = shallowCopy(obj[key]);
            } else {
            // 基本类型则直接赋值
                newObj[key] = obj[key];
            }
        }
    }
    return newObj;
}
测试结果

image.png

基本全部都能进行深拷贝,唯一不同的就是Symbol类型其实这里并不是深拷贝。因为Symbol是原始数据类型之一,和字符串、数字、布尔值等一样,它们在赋值时都是按值传递的。但是,对于Symbol而言,这个“值”更像是一个引用标识符,它指向在全局Symbol注册表中的一个唯一 Symbol 值。所以这里两个对象指向的Symbol其实是同一个值。

结语

面对深拷贝的局限性,开发者还需根据实际情况采取额外措施或寻找更全面的解决方案,如利用第三方库lodash提供的_.cloneDeep方法,来增强深拷贝功能的全面性和实用性。

本次分享到此结束,如果有疑惑或者本文出现错误的地方欢迎大家在评论区指出,喜欢的话就点个关注吧。>_<

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

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

相关文章

【ARM Cache 与 MMU/MPU 系列文章 2.1 -- 什么是 Cache PoP 及 PoDP ?】

请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 PoP 及 PoDPCache PoDPCache PoP应用和影响PoP 及 PoDP Cache PoDP 点对深度持久性(Point of Deep Persistence, PoDP)是内存系统中的一个点,在该点达到的任何写操作即使在系统供电…

图的遍历介绍

概念 特点 无论是进行哪种遍历&#xff0c;均需要通过设置辅助数组标记顶点是否被访问来避免重复访问&#xff01;&#xff01;&#xff01;&#xff01; 类型 深度优先遍历 可以实现一次遍历访问一个连通图中的所有顶点&#xff0c;只要连通就能继续向下访问。 因此&#x…

48【Aseprite 作图】荷塘月色——拆解

1 荷叶&#xff0c;不要完全对称&#xff0c;下面是深色的&#xff0c;上面是浅色的&#xff0c;加一点高光 2 鱼的轮廓 上色彩&#xff0c;主要用三种颜色&#xff0c;修改透明度&#xff0c;叠加颜色

“粘土风格”轻松拿捏,基于函数计算部署 ComfyUI实现AI生图

阿里云函数计算 FC 一键部署火爆全球工作流 AI 生图平台—— ComfyUI &#xff0c;实现更高质量的图像生成&#xff0c;三步轻松完成“黏土”创意AI画作&#xff0c;晒图赢眼部按摩器等好礼&#xff01; 活动地址&#xff1a; https://developer.aliyun.com/topic/june/fcspma…

Vue3【十七】props的作用和组件之间的传值限定类型和默认值

Vue3【十七】props的作用和组件之间的传值限定类型和默认值 Vue3【十七】props的作用和组件之间的传值限定类型和默认值 父组件传值给子组件 多个值传递 传值限定类型和 默认值 实例截图 目录结构 代码 person.vue <template><div class"person"><p…

Python版本管理器-Miniconda

随着Python的版本更新&#xff0c;我们在开发Python软件的时候&#xff0c;对Python的版本选择越来越重要&#xff0c;但同时又要兼容已经开发好了的Python软件&#xff0c;因此选择一款合适的Python版本管理器对提高开发效率也越来越重要&#xff0c;今天就推荐一款Python的版…

InfiniBand网络内计算架构指南

InfiniBand网络内计算知多少&#xff1f; InfiniBand在高性能计算和人工智能领域占据核心地位&#xff0c;其高速、低延迟的网络通信能力支持大规模数据传输与复杂计算。在网络内计算领域&#xff0c;InfiniBand的应用日益广泛&#xff0c;通过内部计算降低延迟&#xff0c;提升…

【JVM】之常见面试题

文章目录 1.JVM中的内存区域划分2.JVM的类加载机制2.1 加载2.2 验证2.3 准备2.4 解析2.5 初始化2.6 类加载的时机 3 类加载器4.双亲委派模型5.JVM中的垃圾回收策略5.1 找谁是垃圾5.1.1 引用计数法5.1.2 可达性分析法 5.2 释放垃圾5.2.1 标记清除算法5.2.2 复制算法5.2.3 标记整…

ASUS华硕ROG幻14Air笔记本GA403UI(UI UV UU UJ)工厂模式原厂Windows11系统安装包,带MyASUS in WinRE重置还原

适用型号&#xff1a;GA403UI、GA403UV、GA403UU、GA403UJ 链接&#xff1a;https://pan.baidu.com/s/1tz8PZbYKakfvUoXafQPLIg?pwd1mtc 提取码&#xff1a;1mtc 华硕原装WIN11系统工厂包带有ASUS RECOVERY恢复功能、自带面部识别,声卡,显卡,网卡,蓝牙等所有驱动、出厂主题…

【Python】已完美解决:(Python键盘中断报错问题) KeyboardInterrupt

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例&#xff08;结合实战场景&#xff09;五、注意事项 已解决&#xff1a;Python中处理KeyboardInterrupt&#xff08;键盘中断&#xff09;报错问题 一、问题背景 在Python编程中&#xff0c;当我们运…

uni-date-picker 禁用日期功能

在uni-datetime-picker组件中 calendar.vue <template><view class"uni-calendar" mouseleave"leaveCale"><view v-if"!insert && show" class"uni-calendar__mask" :class"{uni-calendar--mask-show:an…

Python-Socket网络编程简单示例

# TCP 服务端程序 server.py # 导入socket 库 from socket import *# 主机地址为空字符串&#xff0c;表示绑定本机所有网络接口ip地址 # 等待客户端来连接 IP # 端口号 PORT 50000 # 定义一次从socket缓冲区最多读入512个字节数据 BUFLEN 512# 实例化一个socket对象 # 参…

【kubernetes】k8s集群安全机制 保姆级攻略

目录 一、认证&#xff08;Authentication&#xff09; Kubernetes 作为一个分布式集群的管理工具&#xff0c;保证集群的安全性是其一个重要的任务。API Server 是集群内部各个组件通信的中介&#xff0c; 也是外部控制的入口。所以 Kubernetes 的安全机制基本就是围绕保护 A…

牛客 NC129 阶乘末尾0的数量【简单 基础数学 Java/Go/PHP/C++】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/aa03dff18376454c9d2e359163bf44b8 https://www.lintcode.com/problem/2 思路 Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff…

LabVIEW结构体内部缺陷振动检测

结构体内部缺陷会改变其振动特性&#xff0c;通过振动分析可以检测并定位这些缺陷。本文详细分析内部缺陷对振动的影响&#xff0c;从频谱分析、时域分析和模态分析等多角度探讨基于LabVIEW的检测方法&#xff0c;提供实施步骤和注意事项&#xff0c;帮助工程师有效利用LabVIEW…

1224 - 过河卒

题目描述 AA 点有一个过河卒&#xff0c;需要走到目标 BB 点。 卒行走规则&#xff1a;可以向下、或者向右。同时在棋盘上的任一点有一个对方的马&#xff08;如下图的 CC 点&#xff09;&#xff0c;该马所在的点和所有跳跃一步可达的点称为对方马的控制点。 例如&#xff…

哪个牌子洗地机最好?四款甄选佳品安利,质量放心

作为一个熟悉智能清洁家电的行业者&#xff0c;洗地机可谓是实用性最高的地面清洁工具&#xff0c;这个实用性一方面是清洁力强&#xff0c;它集合了扫地和拖地能力&#xff0c;另一方面是操作方便&#xff0c;清洁速度快。可是面对市面上种类繁多的智能清洁家电&#xff0c;往…

C语言之数组

目录 一、数组的概念 二、一维数组的使用 数组的创建 数组的初始化 数组的使用 三、一维数组在内存中的存储 四、sizeof计算数组元素个数 五、二维数组的使用 数组的创建 数组的初始化 数组的使用 六、二维数组在内存中的存储 七、C99中的变长数组 八、总结 一、…

“JS加密在线”:简单直接的在线JS加密网站

网站名&#xff1a;“JS加密在线”&#xff0c; 功能&#xff1a;JavaScript源代码加密。 UI&#xff1a; http://jsjiami.online/ 非常简洁的JS加密网站&#xff0c;几乎只有两个功能&#xff1a;上传JS文件、下载加密后的JS文件。 JS加密&#xff0c;就应该这样简单直接。…

AI机器人公众号小程序h5源码开源交付支持二开黑色风格版本

AI机器人系统对接OPENAI&#xff1a;开启智能新纪元 更新全新UI、新增全家桶模块、新增热榜板块、支持语音朗读、支持快速回答、支持AI绘图、支持文字一键生成图、支持导出pdf、支持导出word、支持导出文字、支持快速响应、支持中英翻译、支持markdown &#x1f680;一、引言…