js深拷贝与浅拷贝
1.浅拷贝概念
浅拷贝是其属性与拷贝源对象的属性共享相同引用,当你更改源或副本时,也可能(可能说的是只针对引用数据类型)导致其他对象也发生更改。
特性:
- 会新创建一个对象,即obj===obj2返回fasle;
- 对象中如果是基本数据类型会单独开辟一份空间存储,如果是引用数据类型则共用一个内存地址。即如果是基本数据类型新对象修改不会造成源对象值改变,但是如果是引用数据类型,修改会造成源对象属性同时被修改
2.var people1 = people不是浅拷贝
注意var people1 = people不是浅拷贝。只是对内存地址进行赋值,people1 === people 返回true,这种不是浅拷贝
// 这个种方式不是浅拷贝
var people = {name: 'allen'
}// 这里只是对内存地址进行赋值,people1 === people 返回true,这种不是浅拷贝
var people1 = people
people1.name = 'jason'
3.浅拷贝示例
浅拷贝:会新创建一个对象,对源对象的属性进行拷贝,使两者共享同一个地址。obj === obj2返回false。比如:var obj2 = Object.assign({}, obj)

说明:Object.assign()是浅拷贝,会生成一个新的对象。浅拷贝对于基本数据类型a,会重新单独开辟一份空间进行存储, 而对于引用数据类型b拷贝的是其内存地址,所以obj2和obj对于拷贝后的b是共用一份内存地址。所以如果修改obj2中b的b1的值,则obj中的b1的值也会改变
4.浅拷贝的方法(Object.create(),Object.assign(),扩展运算符)
4.1Object.create()
创建一个对象,会将源对象放到新对象的原型上(即会将obj对象放到obj2的原型上),返回一个新的对象。
var obj = {a: 1}
var obj2 = Object.create(obj)
obj.a = 2 //修改基本数据类型,源对象也会改变
console.log(obj === obj2); //false
console.log(obj,obj2);

4.2 Object.assign()
将对象属性进行合并,并返回新的对象,遇到重名对象会进行覆盖
var obj = {a: 1,b: {b1: 1}
}
var obj2 = Object.assign({}, obj)
obj.a = 2
obj.b.b1 = 2console.log(obj === obj2);
console.log(obj, obj2);
结果:源对象基本数据类型值没有改变,引用数据用的同一个会改变

4.3扩展运算符
var obj = {a: 1,b: {b1: 1}
}var obj2 = {...obj};
obj2.a = 3;
obj2.b.b1 = 2;console.log(obj === obj2);
console.log(obj, obj2);
结果:同上

5.深拷贝概念
深拷贝是指其属性与其拷贝的源对象的属性不共享相同的引用,当你更改源或副本时,可以确保不会导致其他对象也发生更改
6.深拷贝的方法
6.1JSON.parse(JSON.stringify())
原理:通过改变数据类型的形式进行深拷贝,JSON.stringify()将对象序列化成字符串,而JSON.parse()将字符串转为对象。注意不是JSON.stringify()是两个方法组合使用
var obj = {a: 1,b: {b1: 1}
}
var obj1 = JSON.parse(JSON.stringify(obj))
obj1.a = 2
obj1.b.b1 = 2
console.log(obj === obj2);
console.log(obj, obj2);
结果:基本数据类型和引用数据类型的改变都不会印象源对象

6.2 Lodash.cloneDeep()
cdn地址 : https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js
import _ form "lodash";var obj = {a: 1,b: {b1: 1}
}
var obj1 = _.cloneDeep(obj)
obj1.a = 2
obj1.b.b1 = 2
7.深拷贝的原理
7.1主要考虑以下三个方面:
- 数据类型的划分
- 递归处理
- 循环引入的处理:循环引入即对象可以一直展开,无限嵌套,无限循环
7.1循环引入:
var obj = {};
obj.a = obj;
console.log(obj);
对象可以一直展开,无限嵌套,无限循环

8.手动实现深拷贝
8.1方式一:简单实现(只判断数据基本类型和针对对象数据结构)
- 判断数据类型,特殊类型直接返回;
- 遍历对象进行递归处理;
function deepClone(obj) {console.log(typeof obj);// 判断如果为null,不等于字符串的object,function, 为Date类型,RegRex类型则直接返回if (obj === null || typeof obj !== 'object' || typeof obj === 'function' || obj instanceof Date || obj instanceof RegExp) {return obj;}if (obj instanceof Object) {const newObj = {};for (let key in obj) {newObj[key] = deepClone(obj[key]);}// 注意是最后return不是在for循环中returnnewObj[key]return newObj;}}var obj = {a: 1,b: {b1: 1}}var obj2 = deepClone(obj);obj2.a = 2;obj2.b.b1 = 2console.log(obj === obj2);console.log(obj, obj2);
8.2 方式二(增强): 针对Map、Set、Array等结构进行深拷贝处理
- 判断数据类型,特殊类型直接返回;
- 遍历对象进行递归处理;
- 对Map,Set,Array数据结构进行处理
- 注意Map,Set,Array各自不同遍历及修改的方法
function deepClone(obj) {// 判断如果为null,不等于字符串的object,function, 为Date类型,RegRex类型则直接返回if (obj === null || typeof obj !== 'object' || typeof obj === 'function' || obj instanceof Date || obj instanceof RegExp) {return obj;}if (obj instanceof Set) { //对于Set数据结构(for of 循环;newSet.add(val)) const newObj = new Set();for (let val of obj) {newObj.add(deepClone(val));}return newObj;} else if (obj instanceof Map) { //对于Map数据结构(for of循环 map.set(key,val))const newObj = new Map();for (let [key, val] of obj) {newObj.set(key, deepClone(val));}return newObj;} else if (obj instanceof Array) { //对于数组数据结构(使用forEach进行循环push进行添加)const newObj = [];obj.forEach(item => {newObj.push(deepClone(newObj[item]));});return newObj} else if (obj instanceof Object) {const newObj = {};for (let key in obj) {newObj[key] = deepClone(obj[key]);}// 注意是最后return不是在for循环中returnnewObj[key]return newObj;} else {return obj;}}var newMap = new Map();newMap.set('key1', 12);newMap.set('key2', 13);var newSet = new Set();newSet.add('11');newSet.add('22');var obj = {a: 1,b: {b1: 1},c: {c1: [1, 2, 3]},d: newMap,f: newSet}var obj2 = deepClone(obj);obj2.a = 2;// 基本数据类型修改值obj2.b.b1 = 2// 数组改变值obj2.c.c1 = [2, 3, 4];// map集合修改key1obj2.d.set('key1','更改后的key1');// Set集合增加一个obj2.f.add('set集合增加的值');console.log(obj === obj2);console.log(obj, obj2);

8.3 方式三(循环引用的处理)
- 判断数据类型,特殊类型直接返回;
- 遍历对象进行递归处理;
- 对Map,Set,Array数据结构进行处理
- 注意Map,Set,Array各自不同遍历及修改的方法
如果有循环引用,使用方式二深拷贝处理,会一直循环导致内存溢出。map = new WeakMap()用于判断是否已经有过相同引用

function deepClone(obj, map = new WeakMap()) {// 判断如果为null,不等于字符串的object,function, 为Date类型,RegRex类型则直接返回if (obj === null || typeof obj !== 'object' || typeof obj === 'function' || obj instanceof Date || obj instanceof RegExp) {return obj;}// 循环引入处理(如果obj下的key的值为obj本身,则循环将obj的值设置到map的key中)// WeakMap的key只能是对象,Set、Map、Array、Object每个都设置map.set(obj,newObj);是因为每种数据结构都有可能存在循环引用if (map.get(obj)) {return map.get(obj);}if (obj instanceof Set) { //对于Set数据结构(for of 循环;newSet.add(val)) const newObj = new Set();map.set(obj, newObj);for (let val of obj) {newObj.add(deepClone(val, map));}return newObj;} else if (obj instanceof Map) { //对于Map数据结构(for of循环 map.set(key,val))const newObj = new Map();map.set(obj, newObj);for (let [key, val] of obj) {newObj.set(key, deepClone(val, map));}return newObj;} else if (obj instanceof Array) { //对于数组数据结构(使用forEach进行循环push进行添加)const newObj = [];map.set(obj, newObj);obj.forEach(item => {newObj.push(deepClone(newObj[item], map));});return newObj} else if (obj instanceof Object) {const newObj = {};map.set(obj, newObj); //此处设置后,后面newObj即使更改,map内存地址使用的是一个所以map的值也会跟着变for (let key in obj) {newObj[key] = deepClone(obj[key], map);}// 注意是最后return不是在for循环中returnnewObj[key]return newObj;} else {return obj;}}// 循环引入var obj3 = {};obj3.a = obj3;var obj4 = deepClone(obj3);obj4.b = obj4;console.log(obj3 === obj4);console.log(obj3, obj4);

相关文章:
js深拷贝与浅拷贝
1.浅拷贝概念 浅拷贝是其属性与拷贝源对象的属性共享相同引用,当你更改源或副本时,也可能(可能说的是只针对引用数据类型)导致其他对象也发生更改。 特性: 会新创建一个对象,即objobj2返回fasle…...
Docker-harbor私有仓库部署与管理
搭建本地私有仓库 #首先下载 registry 镜像 docker pull registry #在 daemon.json 文件中添加私有镜像仓库地址 vim /etc/docker/daemon.json { "insecure-registries": ["20.0.0.50:5000"], #添加,注意用逗号结…...
ArcGIS笔记8_测量得到的距离单位不是米?一经度一纬度换算为多少米?
本文目录 前言Step 1 遇到测量结果以度为单位的情况Step 2 简单的笨办法转换为以米为单位Step 3 拓展:一经度一纬度换算为多少米 前言 有时我们会遇到这种情况,想在ArcGIS中使用测量工具测量一下某一段距离,但显示的测量结果却是某某度&…...
SpringBoot入门详解
目录 因何而生的SpringBoot 单体架构的捉襟见肘 SpringBoot的优点 快速入门 高曝光率的Annotation SpringBoot的工作机制 了解SpringBootApplication SpringBootConfiguration EnableAutoConfiguration 自动配置的幕后英雄:SpringFactoriesLoader Compon…...
数据分析案例-基于snownlp模型的MatePad11产品用户评论情感分析(文末送书)
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...
Leetcode刷题解析——904. 水果成篮
1. 题目链接:904. 水果成篮 2. 题目描述: 你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多地收集水果。然而,农场的主…...
Spring Boot RESTful API
学习到接口部分了,记录一下 关于restful api感觉这篇文章讲的十分详细且通俗易懂一文搞懂什么是RESTful API - 知乎 (zhihu.com) Spring Boot 提供的 spring-boot-starter-web 组件完全支持开发 RESTful API ,提供了 GetMapping:处理get请求…...
k8s day04
昨日内容回顾: - configMap ---> cm 应用场景: 主要用于配置文件的持久化。 - secret 应用场景: 存储敏感数据,并非加密数据。 - pod探针(probe): - livenessProbe: 健康检查探针&#x…...
ESP32-IPS彩屏ST7789-Arduino-简单驱动
目的: 使ESP32能够驱动点亮ST7789显示屏 前提条件: ESP32 ST7789 (240 x240,IPS) 杜邦线 Arduino 过程: 0x00--接线 0x01--驱动: 彩屏驱动库 针对不同的彩屏驱动芯片,常用的 Arduino…...
高效工具类软件使用
高效工具类软件使用 目录概述需求: 设计思路实现思路分析1.Leanote2.Obsidian 的使用 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for…...
批处理文件(.bat)中,dir与tree命令的效果
目录 dir命令 用法 操作 效果 dir /? dir dir D:\111\111_3 dir D:\111 *.mp4 dir D:\111 /ad dir D:\111 /ar dir D:\111 /s dir D:\111\111_3 >1bat.txt dir D:\111 >>1bat.txt tree命令 用法 操作 效果 tree /? tree tree D:\111\111_3 tree…...
STM32 ---- 再次学习STM32F103C8T6/STM32F409IGT6
目录 一、环境搭建及介绍 关于STM32基础介绍 新建工程 外设案例 LED流水灯 蜂鸣器 上拉电阻和下拉电阻知识 电压比较器 c语言基础知识 类型、结构体、枚举 类型int8_t int16_t int32_t 宏替换 #define 和typedef用法 结构体两种填充方法 和 命名规则 枚举用法 常用…...
UE4 EQS环境查询 学习笔记
EQS环境查询对应Actor的范围 EQS环境查询查询对应的类 查询到即有一个蓝色的球在Actor上,里面有位置信息等等 在行为树运行EQS,按键(‘)可以看到Player的位置已经被标记 运行对应的EQS在这里放如EQS就可以了 Generated Point&…...
计算机算法分析与设计(11)---贪心算法(活动安排问题和背包问题)
文章目录 一、贪心算法概述二、活动安排问题2.1 问题概述2.2 代码编写 三、背包问题3.1 问题描述3.2 代码编写 一、贪心算法概述 1. 贪心算法的定义:贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以…...
shell命令以及运行原理
Linux严格意义上说的是一个操作系统,我们称之为“核心(kernel)“ ,但我们一般用户,不能直接使用kernel。 而是通过kernel的“外壳”程序,也就是所谓的shell,来与kernel沟通。如何理解&a…...
MySQL进阶(再论JDBC)——JDBC编程思想的分析 JDBC的规范架构 JDBC相关的类分析
前言 SQL(Structured Query Language)是一种用于管理关系型数据库的标准化语言,它用于定义、操作和管理数据库中的数据。SQL是一种通用的语言,可以用于多种关系型数据库管理系统(RDBMS),如MySQ…...
rabbitMQ的知识点
RabbitMQ是一种消息队列软件,它实现了高度可靠的消息传递机制。RabbitMQ支持多种消息协议,包括AMQP、STOMP、MQTT等,比较灵活。以下是一些rabbitmq的知识点: 1. 消息队列:消息队列是一种分布式系统中广泛使用的通信模…...
EtherNet/IP 库卡机器人和EtherCAT倍福PLC总线协议连接案例
EtherNet/IP 是一种适合于工业环境和对时间要求比较苛刻的应用的网络。而远创智控YC-EIPM-ECT通讯网关,是一款自主研发的EtherNet/IP 从站功能的通讯网关。它不仅可以实现EtherNet/IP 和EtherCAT的无缝连接,还可以将EtherNet/IP 作为从站连接到EtherCAT总…...
微信小程序 uniapp+vue线上洗衣店业务管理系统演89iu2
本课题意在设计一种系统的、基于用户体验的线上洗衣服务模式,具有如下的研究意义: (1)为用户提供更简单、便捷的洗衣服务模式; (2)为智能柜的盈利模式提供了新的方向; (3)通过线上系统、智能柜与洗衣工厂结合的方式,为洗衣企业构建了一套节 省人力成本的…...
Maven项目,进行编译,使用idea的 编译功能,就是正常的,但是在终端中执行 mvn clean compile 报错
一、背景: Maven项目,进行编译,使用idea的 编译功能,就是正常的,但是在终端中执行 mvn clean compile 报错 报错信息: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...
用 FFmpeg 实现 RTMP 推流直播
RTMP(Real-Time Messaging Protocol) 是直播行业中常用的传输协议。 一般来说,直播服务商会给你: ✅ 一个 RTMP 推流地址(你推视频上去) ✅ 一个 HLS 或 FLV 拉流地址(观众观看用)…...
从0开始学习R语言--Day17--Cox回归
Cox回归 在用医疗数据作分析时,最常见的是去预测某类病的患者的死亡率或预测他们的结局。但是我们得到的病人数据,往往会有很多的协变量,即使我们通过计算来减少指标对结果的影响,我们的数据中依然会有很多的协变量,且…...
