js 对象深复制(深拷贝)

【JS专栏】JS对象的浅拷贝与深拷贝 浅拷贝 自己创建一个新的对象,来接受你要重新复制或引用的对象值。如果对象属性是基本的数据类型,复制的就是基本类型的值给新对象;但如果属性是引用数据类型,复制的就是内存中的地址,如果其中一个对象改变了这个内存中的地址,肯定会影响到另一个对象。 ​ 1. object.assign object.assign 是 ES6 中 object 的一个方法,该方法可以用于JS 对象的合并等多个用途,其中一个用途就是可以进行浅拷贝。 该方法的第一个参数是拷贝的目标对象,后面的参数是拷贝的来源对象(也可以是多个来源)。 阅读详情

对象深复制

复制逻辑

什么是深复制和浅复制?JavaScript有6种基本数据类型(Number,Boolean,String、null、udefined和Symbol)和1种引用类型(Object)。

  • 基本数据类型自身变量所指的内存,存的就是自身的值(String例外)
  • 引用数据类型存的是个引用地址(指针),具体数据存在堆中。
  • String在JavaScript比较特殊,它虽然是基本数据类型,但它却是按照引用类型在使用。 对于基本值类型(String)除外,直接复制,要想实现深复制,只要遇到引用类型,必须用new的方式重新创建,并且被复制对象的内部属性,如果是引用,也要这么处理。对象的属性有很多层,这就是深复制实现复杂的原因。

代码实现

首先我们创建一个对象来进行测试
 	  var d = Symbol();
      var e = Symbol();
      var ss = { a: 1 };
      var obj = {
        a: 1,
        b: 2,
        c: [1, 2, 3],
        zz: new Set([1, 2, ss]),
        yy: new Map(),
        [d]: "aaa",
        z: document.createElement("div"),
        d: {
          e: new Date(),
          f: /a/g,
          g: function (s) {
            console.log(s);
          },
          h: {},
        },
      };
      Object.defineProperties(obj.d.h, {
        i: {
          value: 10,
        },
        j: {
          configurable: true,
          writable: true,
          value: [1, 2, 3, 4],
        },
        k: {
          writable: true,
          value: {
            l: {},
            m: "abcde",
            n: true,
            o: [1, 2, 3],
          },
        },
        [e]: {
          value: ["a", "b", "c", "e"],
        },
      });

      Object.defineProperties(obj.d.h.k.l, {
        p: {
          value: function () {
            console.log("p");
          },
        },
        q: {
          value: {
            r: { a: 1 },
            j: { b: 2 },
          },
        },
      });
      var a_1 = { a: 1 };
      var a_2 = { b: 2 };
      obj.yy.set("name", "xietian");
      obj.yy.set(a_1, a_2);

		//对象深复制
const cloneObject = (source, target) => {
  if (source === null || source === undefined) return source;  //判断非空非undefined
  // if (source === document) return;  //非document
  if (!Object.prototype.isPrototypeOf(target)) {   //target是否已经存在对象原型上
    if (HTMLElement.prototype.isPrototypeOf(source)) {  //HTML复制
      target = document.createElement(source.nodeName);
    } else if (source.constructor === RegExp) {  //RegExp复制
      target = new RegExp(source.source, source.flags);
    } else if (source.constructor === Date) {  //Date复制
      target = new Date(source);
    } else if (source.constructor === Function) {   //Function 复制
      var arr = source.toString().replace(/\n|\r/g, "").trim().match(/\((.*?)\)\s*\{(.*)\}/).slice(1);  //进行source处理
      target = new Function(arr[0].trim(), arr[1]);
    } else if (source.constructor === Set) {   //Set复制
      target = new Set(cloneObject(Array.from(source.values())))
    } else if (source.constructor === Map) { // Map复制
      target = new Map();
      // entries() 方法返回一个数组的迭代对象,该对象包含数组的键值对 (key/value)。
      // 迭代对象中数组的索引值作为 key,数组元素作为 value。
      for (var [key, value] of source.entries()) {  //解构赋值
        if (Object.prototype.isPrototypeOf(key)) {   //判断Map中的key和value类型进行后续复制处理 引用类型继续clone
          if (Object.prototype.isPrototypeOf(value)) {
            target.set(cloneObject(key), cloneObject(value));
          } else {
            target.set(cloneObject(key), value);
          }
        } else {
          if (Object.prototype.isPrototypeOf(value)) {
            target.set(key, cloneObject(value));
          } else {
            target.set(key, value);
          }
        }
      }
    } else {
      target = new source.constructor();     //判断完毕后 剩下的数组和对象等 直接new一个source类型
    }
  }
  //getOwnPropertyNames方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。getOwnPropertySymbols返回symbol的值
  var names = Object.getOwnPropertyNames(source).concat(Object.getOwnPropertySymbols(source));
  for (var i = 0; i < names.length; i++) {
    // console.log(names[i]);
    if (source.constructor === Function && names[i] === "prototype") continue;  //函数会比较特殊  在这进行判断函数
    var desc = Object.getOwnPropertyDescriptor(source, names[i]);
    if (Object.prototype.isPrototypeOf(desc.value)) { //函数会因为它的prototype constructor指向的是一个函数 然后函数继续指向函数 所以会死循环
      // 根据需要将源对象的描述内容设置给当前目标对象
      // 相同属性名的描述内容,及值赋为刚才创建相同类型的对象
      Object.defineProperty(target, names[i], {
        enumerable: desc.enumerable,
        configurable: desc.configurable,
        writable: desc.writable,
        value: cloneObject(desc.value)
      });
    } else {
      // 如果描述的对象的值不是引用类型,
      // 直接将描述对象设置给目标对象的这个属性
      Object.defineProperty(target, names[i], desc);
    }
  }
  return target;
}
     
// a_1.a = 100;
// obj.d.h.j[1] = 1000;
const _obj = cloneObject(obj);
console.log(_obj);
AI原生应用在UGC内容审核中的实战经验 AI原生应用(AI-Native Application)——以机器学习模型为核心驱动力,深度整合数据、算法、工程架构的完整系统——为破解这一三角难题提供了全新范式。全链路数据驱动:从数据采集、模型训练到决策优化,形成闭环自治系统,无需人工规则干预多模态深度理解:同时处理文本、图像、音频、视频等多类型内容,理解语义而非简单匹配特征自适应进化能力:通过人机协同反馈持续学习新型违规模式,模型周级迭代成为常态审核效率提升300%:单条视频审核耗时从2.3秒降至0.7秒。 阅读详情

相关推荐

STM32掉电保存配置参数技巧

本文介绍了使用STM32内置备份寄存器(BKP)实现掉电保存配置参数的方法。相比外接EEPROM或Flash,备份寄存器无需外设但存储容量有限,需通过VBAT引脚连接纽扣电池供电。文章详细说明了初始化步骤,包括使能PWR时钟、允许访问备份寄存器等操作,并提供了RTC初始化的代码示例。同时介绍了HAL库中读写备份寄存器的函数使用方法,包括HAL_RTCEx_BKUPWrite和HAL_RTCEx_BKUPRead函数的具体参数和调用示例。该方法适用于需要小容量数据掉电保存的应用场景。

hanhanhan233的博客 948

Js实现深拷贝的4种方式

进行深拷贝的方法:递归函数 (推荐使用,项目中使用的更多,更小,更安全)JSON.stringify() 和JSON.parse();(不推荐使用,如果遇到Function,Date等类型的变量容易出现一些意料之外的问题)第三方库lodash的cloneDeep()方法JQuery的extend()函数 (推荐在JQuery项目中使用,其他项目依然推荐是用递归函数)

weixin_49295874的博客 1万+

使用Bigemap下载地图流程

Bigemap地图下载简单流程,临时安排任务简单学习没有深入了解。

TKY666的博客 4850

4种实现JS深拷贝的方法

上述的几种方式不管优缺点如何,共同点是只能拷贝对象的可枚举属性,对于不可枚举或者原型上的属性,却不能拷贝,但对于基本的使用来说,已经足够了。

sunnyjingqi的博客 5627

CH376S模块实战:如何通过串口轻松实现单片机与U盘的数据交互

本文详细介绍了如何利用CH376S模块,通过串口通信实现单片机与U盘的数据交互。文章从模块原理、硬件连接到核心指令集进行了全面解析,并提供了基于STM32的实战代码示例。CH376S模块极大地简化了USB协议和文件系统的复杂性,使开发者能快速为嵌入式设备添加便捷的数据存储与导出功能,适用于数据记录、配置导入等多种应用场景。

weixin_29165725的博客 458

AutoSAR系列讲解(深入篇)14.7-Mcal Adc配置(上)

详细讲解了ADC的各个配置项的作用

雪云飞星的博客 1万+

JS实现深拷贝的几种方法

通过递归的方式深度遍历对象,将每个属性的值进行复制。需要处理被复制对象为值类型的情况以及属性值中包含对象的情况。需要注意的是,为了防止循环引用导致死循环,需要记录已经遍历过的对象。是一个一致性、模块化、高性能的。

前端学习笔记 4736

【高级强化学习:算法、优化与泛化】第13章 扩散模型策略优化(Diffusion Policy Optimization)

\quad$ 计算均值 $\mu_t = \frac{1}{\sqrt{\alpha_t}} \left( x_t - \frac{1 - \alpha_t}{\sqrt{1 - \bar{\alpha}_t}} \tilde{\epsilon} \right)$.$\quad$ 组合得分估计: $\tilde{\epsilon} = \epsilon_{\text{unc}} + w \cdot (\epsilon_{\text{con}} - \epsilon_{\text{unc}})$.

u012133341的博客 339

JS实现深拷贝的4种方法

进行深拷贝的方法:递归函数 (推荐使用,项目中使用的更多,更小,更安全)JSON.stringify() 和JSON.parse();(不推荐使用,如果遇到Function,Date等类型的变量容易出现一些意料之外的问题)第三方库lodash的cloneDeep()方法JQuery的extend()函数 (推荐在JQuery项目中使用,其他项目依然推荐是用递归函数)到此这篇关于JS实现深拷贝的4种方式的文章就介绍到这了,希望可以帮到你!微点阅读。

xinyuerr的博客 7981

Win11右下角不显示图标怎么办?Win11右下角不显示图标的解决方法

所以有不少符合资格的小伙伴都下载进行体验了,但是有的小伙伴在升级完系统之后发现桌面右下角不显示任何图标,那么遇到这种情况要怎么办呢?下面就和小编一起来看看有什么解决方法吧。2、接着找到任务栏设置中的“taskbar corner overflow”。3、然后在下方勾选打开想要显示的图标程序就可以了。1、首先右键任务栏,在其中选择“任务栏设置”。目前微软已经正式推出了。

2401_88800025的博客 886

外骨骼机器人(二):自适应振荡器

振荡器是一种数学工具,可以用于实时跟踪、预测类周期信号的频率、相位、幅值等,而助行外骨骼机器人需要自动适应人体的行走频率、幅度,两者相结合,就能使助行外骨骼机器人拥有更舒适、更自然的行走步态。 ......

行者无疆的博客 4264

JS深复制对象方法(深拷贝)

前言:在日常开发中需要复制一条数据。此时如果用变量等号赋值或者object.assign();方法,然后操作改变新赋值对象的值会影响原对象的值。此时深拷贝对象就应用而生。// 序列化:对象的类型转换成字符串类型。//反序列化:字符串类型的类型转换成对象。...

书中自有妍如玉的博客 1035

SAPGUI excel 导出时遇到的运行时错误:STRING_SIZE_TOO_LARGE

当报表导出需求远超单一 XLSX 文件的物理承载力时,与其在 SAPGUI 中硬拼 2 GB 限制,不如把分页、过滤、流式写入作为设计前提。掌握 ABAP2XLSX 或 CSV + Power Query 等工具链,既能满足审计合规,又能让应用服务器远离的噩梦。祝你在下一次导出海量数据时,既高效又优雅。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 642

js对象深复制/深拷贝功能函数封装

js对象深复制封装(深拷贝) 深复制,及源对象的属性如果有对象,该对象属性修改后,不会引起复制后的对象各属性的改变, 源对象的任何属性及子属性与新对象的直接没有任何引用关系。 一下例举几种浅复制常见方法: for(var prop in obj){ // 浅复制 } Object.assign();//浅复制 var obj1={...obj};//浅复制 如果原obj1就存在,还会改变原obj1的引用地址

RequesToGod的博客 379

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

JavaScript实现对象或者数组的深拷贝(深复制或者深克隆)

//深克隆 function deepClone(obj){ var cloneObj //当obj是一个简单值时 if(obj && typeof obj!=='object'){ cloneObj=obj console.log("plain value") } //当obj是对象或者数组的时候 else if(obj && typeof obj==='object'){ co

我是小奶音啊的博客 359

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

JS对象深拷贝和浅拷贝

浅复制和深复制都可以实现在已有对象基础上再生一份对象的引用,但是对象的实例存储都是在堆内存中,然后通过一个引用值去操作对象,所以复制对象的时候就会存在两种情况:复制引用和复制实例,这也是浅复制和深复制的区别所在。 浅复制:浅复制是复制对象引用,复制后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响 深复制:深复制不是简单的复制引用,而是在堆中重新分配内存,并且把源对象实例的所有属性都进行...

weixin_34007879的博客 88

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

学习笔记-----js对象里的浅拷贝和深拷贝;数组中的浅复制和深复制;

1.对象 对象浅拷贝: 一个对象的成员复制给另一个对象的成员时,只能把第一层的值给复制过去,若复制的成员中含有对象,那么复制的成员对象复制的只是内存地址,只是将其映射过去,但是并没有重新创建出一个新的内存区域去存这个对象 var obj1 = { name: ‘zs’, age: 18, sex: ‘男’ ; dog: { ///此时修改这个会使obj2中的dog成员里的name属性...

lm_four的博客 212

JavaScript拷贝

JavaScript的浅拷贝与深拷贝

ljx11606的博客 454

js深复制一个数组

复制数组

qq_42931285的博客 702

JSON.stringify 深复制

深复制实现与JSON.stringify

qq_27315289的博客 474

递归深复制对象

递归深复制对象。

m0_55295461的博客 152

js对象的递归深拷贝

上菜~ <script> var obj = { // 定义要进行深复制的对象 name: "张三", age: 14, tel: 110, info: { isSingle: true } } // 定义深复制的函数 function deepClone(params) {

qq_45946424的博客 143

JavaScript递归深复制对象

递归深复制对象 <script> var obj = { // 定义要进行深复制的对象 name: "张三", age: 14, tel: 110, info: { isSingle: true } } // 定义深复制的函数 function deepClone(params) {

weixin_55876727的博客 196

js深拷贝和浅拷贝

一、按值操作(深拷贝) 以下javascript的基本类型, 复制后,修改一个变量的值时,不会影响其他变量的值。 string number boolean null undefined 例如: let age1 = 100; //number类型 let age2 = age1; //值的赋值属于深拷贝 console.log(age1, age2); //100 100 age1 = 200; console.log(age1, age2); //200 100 值的复制:是给另外一个变量创

qq_32339737的博客 167

ECMAScript-14 【三目运算-对象克隆-浅拷贝、深拷贝】

一.三目运算 (1).基本结构 a > 0 ? console.log('大于0') //这里可以写注释 :console.log('小于等于0'); 这么写整洁一点也好写注释,也记住?后面的语句就不要加上分号了 (2).接收结果 可以直接接收结果 var str = a > 0 ? '大于0' :'小于0' (3).嵌套 str = a > 0 ?( a > 3 ? '大于3'

Yesterday_Tomorrow的博客 278

html——js 对象的深浅复制拷贝问题

1、js如果使用等于号直接赋值对象,那么对该对象是浅复制,当一个对象的值被修改,那么另一个对象的值也会被修改。 2、若要使用深复制,可以采用JSON.stringify/parse方法: let arr1 = [1,2,3,4]; let arr2 = JSON.parse(JSON.stringify(arr1)); arr2.push(5); console.log(arr1); //[1, ...

知北行的博客 511
上一篇: 理解科里化函数(currying)及应用场景
下一篇: 写 JS 逻辑判断,不要只知道用 if-else 和 switch(转载)
MaxLoongLvs
博客等级 码龄9年 226粉丝 170原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MaxLoongLvs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值