1. 什么是深拷贝和浅拷贝:

    深拷贝针对的是复杂的 Object 数据类型,深拷贝需要将属性的各个层级都要拷贝过来。
    深拷贝将另一个对象的属性值拷贝过来之后,另一个对象的属性值并不受到影响,因为它自己在堆中开辟了自己的内存区域,不受外界干扰。

    浅拷贝主要拷贝的是对象的引用值,当改变对象的值,另一个对象的值也会发生变化。

    例子:js中的slice() 方法不能达到完全的深拷贝, 一维数组可以深拷贝,当改变a[0]的值后,打印处a的值改变,b的值并不受到影响,仍然是[1,2,3,4]。

    //一维数组的slice
    let a = [1, 2, 3, 4],b = a.slice();a[0] = 5;
    console.log(a);  //[ 5, 2, 3, 4 ]
    console.log(b);  //[ 1, 2, 3, 4 ]b[0] = 10;
    console.log(a); //[ 5, 2, 3, 4 ]
    console.log(b); //[ 10, 2, 3, 4 ]

    换一个多层级的数组:

    let a=[0,1,[2,3],4],
    b = a.slice();a[0]=2;
    a[2][0]=1;
    console.log(a);  //[ 2, 1, [ 1, 3 ], 4 ]
    console.log(b);  //[ 0, 1, [ 1, 3 ], 4 ]

    二维数组中slice() 拷贝并不彻底,二级属性没能拷贝成功,b仍脱离不了a的控制,说明slice不是真正的深拷贝。
    同理,concat 方法不是真正的深拷贝,也存在这样的情况

  2. 扩展运算符和 Object.assign() 都不是深拷贝
    扩展运算符:

    let outObj = {inobj: {a: 1,b: 2}
    }
    let newObj = {...outObj
    }
    newObj.inobj.a = 2
    console.log(outObj);   //{ inobj: { a: 2, b: 2 } }

    Object.assign():浅拷贝

    let outObj = {inObj:{a:1,b:2}
    }
    let newObj = Object.assign({},outObj);
    newObj.inObj.a = 2;
    console.log(outObj);    //{ inObj: { a: 2, b: 2 } }

    只有一层嵌套是可以的,所以能否深拷贝要看数据结构怎么设计的。

  3. 实现深拷贝的三个办法:
    JSON.parse(JSON.stringfy()): 这个方法很简单 ,但不能拷贝函数。遇到正则会变成对象。

    let outObj = {foo: 1,inObj: { a: 1, b: 2 },bar: function () { }
    }
    let newObj = JSON.parse(JSON.stringify(outObj));console.log(newObj);   //{ foo: 1, inObj: { a: 1, b: 2 } }newObj.inObj.a = 2;console.log(outObj);  //{ foo: 1, inObj: { a: 1, b: 2 }, bar: [Function: bar] }
    console.log(newObj)   //{ foo: 1, inObj: { a: 2, b: 2 } }
  4. 用 for...in 遍历和复制实现一个深拷贝方法:

    const deepClone = (obj) => {if (typeof obj !== 'object') returnlet newObj = obj instanceof Array ? [] : {}for (let key in obj) {if (typeof obj[key] === 'object') {newObj[key] = deepClone(obj[key])} else {newObj[key] = obj[key]}}return newObj
    }
    

    将上面的例子拿来验一下:

    let outObj = {foo: 1,inObj: { a: 1, b: 2 },bar: function () { }
    }
    let objCopy = deepClone(outObj);
    console.log(objCopy);    //{ foo: 1, inObj: { a: 1, b: 2 }, bar: [Function: bar] }objCopy.inObj.a = 2;
    console.log(objCopy);    //{ foo: 1, inObj: { a: 2, b: 2 }, bar: [Function: bar] }
    console.log(outObj);    //{ foo: 1, inObj: { a: 1, b: 2 }, bar: [Function: bar] }

    复杂对象的处理:

    const allRoomPos = {"幻灵": {'p1': { 'x': 1000, 'y': 615 },'p2': { 'x': 1000, 'y': 670 },'p3': { 'x': 935, 'y': 670 },'p4': { 'x': 935, 'y': 615 }},"仙游": {'p1': { 'x': 1000, 'y': 515 },'p2': { 'x': 1000, 'y': 580 },'p3': { 'x': 935, 'y': 580 },'p4': { 'x': 935, 'y': 515 }},
    }let copyRoompos = deepClone(allRoomPos);
    console.log(copyRoompos);
    /*
    { '幻灵':{ p1: { x: 1000, y: 615 },p2: { x: 1000, y: 670 },p3: { x: 935, y: 670 },p4: { x: 935, y: 615 } },'仙游':{ p1: { x: 1000, y: 515 },p2: { x: 1000, y: 580 },p3: { x: 935, y: 580 },p4: { x: 935, y: 515 } } }
    */console.log(allRoomPos)
    /*
    { '幻灵':{ p1: { x: 1000, y: 615 },p2: { x: 1000, y: 670 },p3: { x: 935, y: 670 },p4: { x: 935, y: 615 } },'仙游':{ p1: { x: 1000, y: 515 },p2: { x: 1000, y: 580 },p3: { x: 935, y: 580 },p4: { x: 935, y: 515 } } }
    */
  5. 利用数组的 Array.prototype.forEach 和 ECMAScript 5 中的Object.* 函数实现深拷贝:

    var deepClone = function (obj) {var copy = Object.create(Object.getPrototypeOf(obj));var propNames = Object.getOwnPropertyNames(obj);propNames.forEach(function (name) {var desc = Object.getOwnPropertyDescriptor(obj, name);Object.defineProperty(copy, name, desc);});return copy;
    }var obj1 = {family: { brother: "wangzhipeng", father: "wanglicai", mother: "sunaiyun" },name: "gino",sex: "male",age: "27"
    };var obj2 = deepClone(obj1);
    obj1.sex = "close";
    console.log(obj1);
    /*
    { family:{ brother: 'wangzhipeng',father: 'wanglicai',mother: 'sunaiyun' },name: 'gino',sex: 'close',age: '27' }
    */console.log(obj2);
    /*
    { family:{ brother: 'wangzhipeng',father: 'wanglicai',mother: 'sunaiyun' },name: 'gino',sex: 'male',age: '27' }
    */

浅拷贝和深拷贝三种方法相关推荐

  1. java数据输入的步骤_Java学习日志1.4 Scanner 数据输入的三种方法

    Scanner sc = new Scanner(System.in); /注意in 是InputStream的缩写,是字节输入流的意思. 整句话的含义就是: new 一个对象,接受从键盘输入的数据, ...

  2. RedHat 7.0及CentOS 7.0禁止Ping的三种方法

    作者:荒原之梦 原文链接:http://zhaokaifeng.com/?p=538 前言: "Ping"属于ICMP协议(即"Internet控制报文协议") ...

  3. 结构成员访问的三种方法

    结构成员访问的三种方法 #include "stdio.h" #include "string.h" #include <stdlib.h> mai ...

  4. html手机不能自动播放音乐,解决移动端浏览器 HTML 音频不能自动播放的三种方法...

    由于Android,IOS移动端的浏览器以及微信自带的浏览器为了用户更好的体验,规定不自动播放音频视频,默认屏蔽了autoplay,如果要想达到自动播放效果,需要单独处理,方法有以下几种: 第一种:添 ...

  5. 在JavaScript中重复字符串的三种方法

    In this article, I'll explain how to solve freeCodeCamp's "Repeat a string repeat a string" ...

  6. Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法...

    Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法 www.MyException.Cn   发布于:2012-09-15 ...

  7. vue项目刷新当前页面的三种方法

    本文介绍了vue项目刷新当前页面的三种方法,本文图文并茂给大家介绍的非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下. 想必大家在刨坑vue的时候也遇到过下面情形:比如在删除或者增加一条记录的时 ...

  8. 【数学知识】三种方法求 [1,n] 中所有数欧拉函数(线性筛欧拉函数优化至 O(n) )

    整理的算法模板合集: ACM模板 ①直接求小于或等于n,且与n互质的数个数(求[1,n]中所有数的欧拉函数时间复杂度:O(nn)O(n\sqrt{n})O(nn​)) ②求[1,n]之间每个数的质因数 ...

  9. php遍历数组哪个效率高,PHP遍历数组的三种方法及效率对比分析

    PHP遍历数组的三种方法及效率对比分析 发布于 2015-03-04 21:55:27 | 129 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertext ...

最新文章

  1. 一分钟详解点云配准ICP方法
  2. PMP47个过程的ITO
  3. Shell 下记录程序运行时间
  4. cv2.resize
  5. 【Android UI设计与开发】第07期:底部菜单栏(二)Fragment的详细介绍和使用方法
  6. congatec AG acquires Real-Time Systems GmbH
  7. mysql 5.6.41编译安装详细步骤
  8. 斗鱼第三方开放平台2.2版使用记录
  9. 超 60 万 GPS 定位服务被曝漏洞,用户信息或将暴露!
  10. TCP三次握手与四次挥手的过程及原因
  11. 【转】Android 9 Pie 兼容性常见问题及注意事项
  12. NB-IOT平台之电信平台FOTA 升级记录
  13. java 找出重复的数字
  14. echarts:柱状图去掉网格线
  15. The Rust Programming Language - 第14章 更多关于Cargo和Crates.io的内容 - 14.2 将crate发布到Crate.io
  16. win10服务器密码怎么修改,win10服务器ip地址修改密码
  17. 计算机专业英语中tour的意思,tour旅游 (英语小记)
  18. 鸿蒙系统别的手机厂商可以用,鸿蒙有望适配国内其他手机厂商,别再黑了
  19. 深度学习之---loss等于87.336
  20. 2p C和3p C的区别

热门文章

  1. rtl8192 调试
  2. The Cluster ID xxx doesn't match stored clusterId Some(xxx) in meta.properties. The broker is trying
  3. 英文简历要用到的各种词汇
  4. 以下是UNIX linux 下c语言的图形编程  curses库
  5. 关于git,这一篇git命令汇总解析就够了
  6. 用ArcGIS API for JavaScript制作三维可视化图
  7. 基于MNIST数据集实现车牌识别--初步演示版
  8. 单片机能运行操作系统吗?
  9. 免费的录频软件WIN10的WIN+G
  10. think.class.php错误,thinkphp源码分析(四)—错误及异常处理篇