js 拷贝-包含处理循环引用问题

在 JavaScript 中,拷贝对象和数组时需要特别注意,因为对象和数组是引用类型,直接赋值只会复制引用,而不是实际的数据。以下是几种常见的拷贝方法及其应用场景:

1. 浅拷贝(Shallow Copy)

浅拷贝只会复制对象或数组的第一层,而不会递归复制其内部的嵌套对象或数组。

1.1 使用 Object.assign

Object.assign 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它只会复制第一层属性。

const obj1 = { a: 1, b: { c: 2 } };
const obj2 = Object.assign({}, obj1);console.log(obj2); // 输出:{ a: 1, b: { c: 2 } }
console.log(obj2 === obj1); // 输出:false
console.log(obj2.b === obj1.b); // 输出:true 如果是深拷贝,这里应该是false。因为b是引用类型的数据
1.2 使用扩展运算符(Spread Operator)

扩展运算符 ... 可以用于对象和数组,实现浅拷贝。

const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { ...obj1 };console.log(obj2); // 输出:{ a: 1, b: { c: 2 } }
console.log(obj2 === obj1); // 输出:false
console.log(obj2.b === obj1.b); // 输出:true
1.3 使用 Array.prototype.slice 和扩展运算符

对于数组,可以使用 slice 和扩展运算符实现浅拷贝。

const arr1 = [1, 2, [3, 4]];
const arr2 = [...arr1];console.log(arr2); // 输出:[1, 2, [3, 4]]
console.log(arr2 === arr1); // 输出:false
console.log(arr2[2] === arr1[2]); // 输出:true

2. 深拷贝(Deep Copy)

深拷贝会递归复制对象或数组的所有层级,包括嵌套的对象和数组。

2.1 使用 JSON.parseJSON.stringify

JSON.parseJSON.stringify 可以实现简单的深拷贝,但只适用于不含函数、undefinedDate 等特殊类型的对象,并且他也无法处理循环引用的问题。

const obj1 = { a: 1, b: { c: 2 } };
const obj2 = JSON.parse(JSON.stringify(obj1));console.log(obj2); // 输出:{ a: 1, b: { c: 2 } }
console.log(obj2 === obj1); // 输出:false
console.log(obj2.b === obj1.b); // 输出:false
2.2 使用递归函数

可以编写一个递归函数来实现深拷贝。并且也可以解决循环引用的问题

function deepClone(objValue) {// 定义一个缓存的mapconst cache = new WeakMap() // 为什么用WeakMap 而不用Map,因为WeakMap 可以垃圾回收function _deepClone(obj) {//  判断是否是非对象类型(即基本数据类型)if (obj === null || (obj instanceof Object === false)) {return obj;}if (cache.has(obj)) {// 新增代码,查哈希表return cache.get(obj)}let target = Array.isArray(obj) ? [] : {}cache.set(obj, target)// 哈希表设值for (let i in obj) {// 判断是否是自身属性,而不是继承来的属性if (obj.hasOwnProperty(i)) {if (obj[i] instanceof Object === true) {// 判断是不是引用类型target[i] = _deepClone(obj[i])} else {target[i] = obj[i]}}}return target;}return _deepClone(objValue)
}
const obj1 = { a: 1, arr:[1,2,3] };
obj1.sub=obj1
obj1.arr.push(obj1)
const newObj= deepClone(obj1);console.log(newObj.arr!==obj1.arr); // true
console.log(newObj.sub!== obj1.sub); // true
console.log(newObj.arr[3]!== obj1); // true
console.log(newObj.arr[3]=== newObj); // true

3. 使用第三方库

3.1 使用 Lodash 的 _.cloneDeep

Lodash 是一个功能丰富的 JavaScript 实用工具库,提供了 _.cloneDeep 方法来实现深拷贝。

import _ from 'lodash';const obj1 = { a: 1, b: { c: 2 } };
const obj2 = _.cloneDeep(obj1);console.log(obj2); // 输出:{ a: 1, b: { c: 2 } }
console.log(obj2 === obj1); // 输出:false
console.log(obj2.b === obj1.b); // 输出:false

总结

  • 浅拷贝:适用于不需要递归复制嵌套对象或数组的场景。

    • Object.assign
    • 扩展运算符 ...
    • Array.prototype.slice 和扩展运算符
  • 深拷贝:适用于需要递归复制嵌套对象或数组的场景。

    • JSON.parseJSON.stringify(不支持特殊类型)
    • 递归函数
    • 第三方库(如 Lodash 的 _.cloneDeep

根据实际需求选择合适的拷贝方法,可以高效地实现对象和数组的拷贝。

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

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

相关文章

oracle将varchar2 转为clob类型存储。 oracle不支持直接使用sql,将 varchar2 到clob的类型转换,需要下面操作

将一个现有表中的 VARCHAR2 列数据迁移到一个 CLOB 列的过程。以下是对每一步操作的说明: 1. 添加一个新的 CLOB 类型列 首先,向表中添加一个新的 CLOB 类型的列。这个列将用来存储原本的 VARCHAR2 数据。 ALTER TABLE your_table ADD (new_column CL…

Dynamics 365 Business Central Recurring Sales Lines 经常购买销售行 来作 订阅

#D365 BC ERP# #Navision# 前面有节文章专门介绍了BC 2024 Wave 2 支持的更好的Substription & Recurring Billing。 其实在D365 BC ERP中一直有一个比较简单的订阅模块Recrring Sales Lines。本文将介绍一下如何用Recurring Sales Lines来 实施简易的订阅Substription。具…

算法比赛中常用的数学知识

一、求某个整数的正约数个数与正约数之和 1.1求某个正整数N的正约数个数 public class Main {public static void main(String[] args) {System.out.println(count(360));//结果为24}public static long count(long number){long count1;for(long i2;i<Math.sqrt(number);…

虚拟Ubuntu系统 开机提示:SMBus Host controller not enabled 后正常启动,去除这个提示提升开机速度。

如题&#xff0c;虚拟机中的Ubuntu系统开机提示&#xff1a;SMBus Host controller not enabled&#xff0c;虽然能正常启动&#xff0c;但不仅影响开机速度&#xff0c;而且还膈应人。 使用命令查看模块 lsmod | grep piix4 发现i2c_piix4有问题&#xff0c; 禁止 i2c_piix4…

NLP基础知识 与 词向量的转化方法 发展

目录 1.NLP 基础知识点 为什么需要自然语言处理? 自然语言处理有哪些分类? 自然语言处理有哪些实际应用? 为什么需要自然语言处理? 自然语言处理有哪些分类? 自然语言处理有哪些实际应用? 自然语言处理的技术/工作原理是什么? 2.NLP文本转化为词向量的方法 2…

【FPGA基础学习】状态机思想实现流水灯

目录 一、用状态机实现LED流水灯1.状态机思想简介1. 1基本概念1.2.核心要素1.3分类与模型 2.LED流水灯 二、CPLD与FPGA1.技术区别2.应用场景3.设计选择建议 三、HDLbits组合逻辑题目 一、用状态机实现LED流水灯 1.状态机思想简介 1. 1基本概念 ​ 状态机&#xff08;Finite …

CSS语言的游戏AI

CSS语言的游戏AI探讨 随着技术的飞速发展&#xff0c;游戏行业也在不断地革命和演变。游戏中的人工智能&#xff08;AI&#xff09;作为一种重要的设计元素&#xff0c;其复杂性和智能程度对游戏的体验、玩法和整体表现都有着深远的影响。近年来&#xff0c;CSS&#xff08;Ca…

docker配置redis容器时配置文件docker-compose.yml示例

1.配置数据节点&#xff08;主从节点&#xff09; version: 3.7 services:master:image: redis:5.0.9container_name: redis-masterrestart: alwayscommand: redis-server --appendonly yesports:- 6379:6379slave1:image: redis:5.0.9container_name: redis-slave1restart: a…

【WPF】IOC控制反转的应用:弹窗但不互相调用ViewModel

全称&#xff1a;Inversion of Control&#xff0c;控制反转 场景&#xff1a;A页面需要调用B/C页面等&#xff0c;防止直接在VM中新建别的页面实例&#xff0c;使用IOC设计架构&#xff1b; 创建Service&#xff0c;在Service中实现页面的实例创建和定义页面输入输出参数。 在…

MySQL学习笔记十五

第十七章组合查询 17.1组合查询 MySQL允许执行多个查询&#xff08;多条SELECT语句&#xff09;&#xff0c;并将结果作为单个查询结果集返回。这些组合查询通常称为并&#xff08;union&#xff09;或复合查询&#xff08;compound query&#xff09;。 以下几种情况需要使…

【MySQL】安装

下载 MySQL :: MySQL Downloads 安装 mysql 验证

ffpyplayer+Qt,制作一个视频播放器

ffpyplayerQt&#xff0c;制作一个视频播放器 项目地址FFmpegMediaPlayerVideoWidget 项目地址 https://gitee.com/chiyaun/QtFFMediaPlayer FFmpegMediaPlayer 按照 QMediaPlayer的方法重写一个ffpyplayer # coding:utf-8 import logging from typing import Unionfrom PySide…

Spring Boot 国际化配置项详解

Spring Boot 国际化配置项详解 1. 核心配置项分类 将配置项分为以下类别&#xff0c;便于快速定位&#xff1a; 1.1 消息源配置&#xff08;MessageSource 相关&#xff09; 控制属性文件的加载、编码、缓存等行为。 配置项作用默认值示例说明spring.messages.basename指定属…

拍摄的婚庆视频有些DAT的视频文件打不开怎么办

3-12 现在的婚庆公司大多提供结婚的拍摄服务&#xff0c;或者有一些第三方公司做这方面业务&#xff0c;对于视频拍摄来说&#xff0c;有时候会遇到这样一种问题&#xff0c;就是拍摄下来的视频文件&#xff0c;然后会有一两个视频文件是损坏的&#xff0c;播放不了&#xff0…

【力扣hot100题】(073)数组中的第K个最大元素

花了两天时间搞明白答案的快速排序和堆排序。 两种都写了一遍&#xff0c;感觉堆排序更简单很多。 两种都记录一下&#xff0c;包括具体方法和易错点。 快速排序 class Solution { public:vector<int> nums;int quicksort(int left,int right,int k){if(leftright) r…

【亲测】Linux 使用 Matplotlib 显示中文

文章目录 安装中文字体在Matplotlib中使用该字体来显示中文 在 Linux 系统中使用 Matplotlib 绘制图表时&#xff0c;如果需要显示中文&#xff0c;可能会遇到中文字符显示为方块或者乱码的问题。这是因为Matplotlib 默认使用的字体不支持中文。本文手把手带你解决这个问题。 …

Redis Java 客户端 之 SpringDataRedis

SpringDataRedis SpringData是Spring中数据操作的模块&#xff0c;包含对各种数据库的集成&#xff0c;其中对Redis集成模块就叫做SpringDataRedis&#xff0c; 官方地址&#xff1a;https://spring.io/projects/spring-data-redis 特性&#xff1a; 提供了对不同Redis客户端…

数字化转型:重构生存逻辑,不止系统升级

数字化转型不过是升级系统&#xff0c;砸了钱、耗了力&#xff0c;却没达到预期&#xff0c;竞争力也没提升。实际上&#xff0c;数字化转型是对企业生存逻辑的彻~底重构&#xff0c;关乎商业模式、运营流程等方方面面。​ 很多企业觉得数字化转型是 IT 部门的事&#xff0c;只…

C语言队列的实现

目录 ​编辑 &#xff08;一&#xff09;队列的定义,初始化及创建结点 &#xff08;二&#xff09;入队和出队&#xff0c;以及取队头队尾的数据 (三)销毁队列 队列是指只允许在一端进行插入数据操作&#xff0c;在另⼀端进行删除数据操作的特殊线性表&#xff0c;队列具有先…

mapbox进阶,使用本地dem数据,加载hillshade山体阴影图层

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️hillshade 山体阴影图层 api1.3.1 ☘️…