对象深复制

复制逻辑

什么是深复制和浅复制?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;  //非documentif (!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类型进行后续复制处理 引用类型继续cloneif (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);

js 对象深复制(深拷贝)相关推荐

  1. JS对象拷贝:深拷贝和浅拷贝

    摘要:对象拷贝,简而言之就是将对象再复制一份,但是,复制的方法不同将会得到不同的结果. 本文分享自华为云社区<js对象深浅拷贝,来,试试看!>,作者: 北极光之夜.. 一.速识概念: 对象 ...

  2. js对象浅拷贝与深拷贝

    一.简介    浅拷贝是拷贝一层,如果数据是基本数据类型,会拷贝其本身,如果除了基本数据类型之外还有一层对象,那么只能拷贝其引用,对象的改变会反应到拷贝对象上.    深拷贝是拷贝多层,每一层的数据都 ...

  3. 一行代码完成js对象数组的深拷贝

    1.对于普通数组(数组元素为数字或者字符串),深拷贝很简单,拷贝之后两个数组指针指向的存储地址不同,从而完成深拷贝 var _test = [1,2,3];//原数组 var _testCopy =  ...

  4. js对象、数字深拷贝方式(转)

    知识点一:js中的对象 谈到对象的拷贝,必定要说一下对象的概念.js中的数据类型分为两大类:原始类型和对象类型.(1)原始类型包括:数值.字符串.布尔值.null.undefined(后两个是特殊的原 ...

  5. js 对象浅拷贝和深拷贝

    var model={name:"boy",age:13}; var CopyModel=model; console.log(CopyModel.name); model.nam ...

  6. JavaScript中对象深复制

    参考: http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ 本文转自 ...

  7. JavaScript 复制对象与Object.assign方法无法实现深复制

    在JavaScript这门语言中,数据类型分为两大类:基本数据类型和复杂数据类型.基本数据类型包括Number.Boolean.String.Null.String.Symbol(ES6 新增),而复 ...

  8. C++深复制(深拷贝)、浅复制(浅拷贝)和复制构造函数(拷贝构造函数)详解+实例

    转载出处:https://blog.csdn.net/sxhelijian/article/details/23209967 对象的复制 对于普通类型的对象来说,它们之间的复制是很简单的,例如: in ...

  9. Copy(定义,特点,深复制,浅复制)(非ARC,ARC的运用范围)

    什么是copy? Copy的字面意思是"复制","拷贝",是一个产生副本的过程. 作用:利用一个源对象产生一个副本对象. 特点: 1,修改源对象的属性和行为,不 ...

最新文章

  1. python从list列表中选出一个数和其对应的坐标
  2. OpenCvSharp中CV_8UC1,CV_8UC2等参数的解释
  3. 聚类之K-means均值聚类
  4. static在内存层面的作用_static的作用和内存划分?
  5. QT的QTreeWidgetItem类的使用
  6. navicat 导入SQL文件出错
  7. cad万能字体_CAD图纸问号“?”的处理
  8. java 面向对象继承的思想_Java面向对象思想!
  9. 用Layer.search快速查询图元
  10. Linux 命令(52)—— ipcrm 命令
  11. 边缘检测算法_机器视觉怎样检测产品边缘
  12. 定义一个内核panic问题
  13. Python正则表达式去除符号
  14. SAP中通过删除新建未记账成本要素期间的方式更改成本要素类别
  15. 如何为计算机设置ip地上,电脑ip地址设置为多少
  16. 视频分辨率过高,导致部分手机播放失败
  17. AppLocker绕过之路
  18. matlab限幅器无饱和怎么设置,基于MATLAB 的直流电动机双闭环调速系统的仿真研究...
  19. 人脸识别考勤系统解决方案
  20. 不可小觑的吃内存大户

热门文章

  1. Python exec函数
  2. NDCG原理及代码实现
  3. 敏捷模型的优点与缺点
  4. Android9 原生系统网络感叹号消除
  5. 五、JAVA调用海康威视SDK实现摄像头内网转外网并前端展示
  6. vue项目token过期
  7. 2020-05-26 日常问题:关于LOG4J 日志配置文件模版
  8. miui android 8.0 彩蛋,关于小米8探索版的13个隐藏彩蛋:只有真爱米粉看得懂
  9. 深入剖析Glide源码-4.15版本(一)
  10. 孤尽训练营打卡日记day24--系统安全规约