博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅拷贝和深拷贝
阅读量:6604 次
发布时间:2019-06-24

本文共 3806 字,大约阅读时间需要 12 分钟。

1.数组的拷贝(二维数组的拷贝(深拷贝)方法,请看到最后。。。)

//一纬数组,通过slice、concat,Array.from()方法可以实现var arr1 = [1, 2], arr2 = arr1.slice();console.log(arr1); //[1, 2]console.log(arr2); //[1, 2]arr2[0] = 3; //修改arr2console.log(arr1); //[1, 2]console.log(arr2); //[3, 2]

  

//二维数组,拷贝完之后修改值,会同时改变被拷贝的数组,拷贝失败var arr1 = [1, 2, [3, 4]], arr2 = arr1.slice();console.log(arr1); //[1, 2, [3, 4]]console.log(arr2); //[1, 2, [3, 4]]arr2[2][1] = 5; console.log(arr1); //[1, 2, [3, 5]]console.log(arr2); //[1, 2, [3, 5]]

2.对象的一纬(浅)拷贝

//通过object.assign()可实现一纬对象的拷贝var obj1 = {x: 1, y: 2}, obj2 = Object.assign({}, obj1);console.log(obj1) //{x: 1, y: 2}console.log(obj2) //{x: 1, y: 2}obj2.x = 2; //修改obj2.xconsole.log(obj1) //{x: 1, y: 2}console.log(obj2) //{x: 2, y: 2}var obj1 = {    x: 1,     y: {        m: 1    }};var obj2 = Object.assign({}, obj1);console.log(obj1) //{x: 1, y: {m: 1}}console.log(obj2) //{x: 1, y: {m: 1}}obj2.y.m = 2; //修改obj2.y.mobj2.x = 2; //修改obj2.x//结果显示,obj1的一维x对应着没有改变,说明一纬拷贝成功,但是obj1的二维y.m却改变了,说明深拷贝不成功,拷贝成功的结果应该就是前后两个对象完全脱离联系,改变其中一个,另一个没变化才对console.log(obj1) //{x: 1, y: {m: 2}}console.log(obj2) //{x: 2, y: {m: 2}}

3.对象的深拷贝

//方法一,通过JSON.parse(JSON.stringify(obj)),但是有一定的弊端//以下是一般情况下的使用var obj1 = {    x: 1,     y: {        m: 1    }};var obj2 = JSON.parse(JSON.stringify(obj1));console.log(obj1) //{x: 1, y: {m: 1}}console.log(obj2) //{x: 1, y: {m: 1}}obj2.y.m = 2; //修改obj2.y.mconsole.log(obj1) //{x: 1, y: {m: 1}}console.log(obj2) //{x: 2, y: {m: 2}}//以下是会出现问题的使用var obj1 = {    x: 1,    y: undefined,    z: function add(z1, z2) {        return z1 + z2    },    a: Symbol("foo")};var obj2 = JSON.parse(JSON.stringify(obj1));console.log(obj1) //{x: 1, y: undefined, z: ƒ, a: Symbol(foo)}console.log(JSON.stringify(obj1)); //{"x":1}console.log(obj2) //{x: 1}//总结:undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。//方法二(有一定瑕疵的递归),使用递归function deepCopy(obj) {    // 创建一个新对象    let result = {}    let keys = Object.keys(obj),        key = null,        temp = null;    for (let i = 0; i < keys.length; i++) {        key = keys[i];            temp = obj[key];        // 如果字段的值也是一个对象则递归操作        if (temp && typeof temp === 'object') {            result[key] = deepCopy(temp);        } else {        // 否则直接赋值给新对象            result[key] = temp;        }    }    return result;}var obj1 = {    x: {        m: 1    },    y: undefined,    z: function add(z1, z2) {        return z1 + z2    },    a: Symbol("foo")};var obj2 = deepCopy(obj1);obj2.x.m = 2;console.log(obj1); //{x: {m: 1}, y: undefined, z: ƒ, a: Symbol(foo)}console.log(obj2); //{x: {m: 2}, y: undefined, z: ƒ, a: Symbol(foo)}//方法三(完美方法,同时解决了循环引用的问题)(同时适用于数组,因为数组也是特殊的object)//循环引用的案例var obj1 = {    x: 1,     y: 2};obj1.z = obj1;var obj2 = deepCopy(obj1);//解决了循环引用的完美深拷贝方法如下:function deepCopy(obj, parent = null) {    // 创建一个新对象    let result = {};    let keys = Object.keys(obj),        key = null,        temp= null,        _parent = parent;    // 该字段有父级则需要追溯该字段的父级    while (_parent) {        // 如果该字段引用了它的父级则为循环引用        if (_parent.originalParent === obj) {            // 循环引用直接返回同级的新对象            return _parent.currentParent;        }        _parent = _parent.parent;    }    for (let i = 0; i < keys.length; i++) {        key = keys[i];        temp= obj[key];        // 如果字段的值也是一个对象        if (temp && typeof temp=== 'object') {            // 递归执行深拷贝 将同级的待拷贝对象与新对象传递给 parent 方便追溯循环引用            result[key] = DeepCopy(temp, {                originalParent: obj,                currentParent: result,                parent: parent            });        } else {            result[key] = temp;        }    }    return result;}var obj1 = {    x: 1,     y: 2};obj1.z = obj1;var obj2 = deepCopy(obj1);console.log(obj1); //太长了去浏览器试一下吧~ console.log(obj2); //太长了去浏览器试一下吧~

  

  

转载于:https://www.cnblogs.com/xuanbingbingo/p/9006430.html

你可能感兴趣的文章
【转自论坛】如何增加表空间的大小
查看>>
【总结整理】《人人都是产品经理》---读后感
查看>>
session与cookie的区别
查看>>
java 获取IP地址
查看>>
框框下面的小箭头的实现
查看>>
android studio解决微信登录,百度地图等调试问题
查看>>
ural 1109,NYOJ 239,匈牙利算法邻接表
查看>>
P147、面试题26:复杂链表的复制
查看>>
文件及IO操作(三)
查看>>
割点与桥
查看>>
51.字符串操作函数
查看>>
ASP.NET MVC5中View显示Html
查看>>
Eclipse连接到My sql数据库的操作总结/配置数据库驱动
查看>>
python 将unicode编码转换为汉字的几种方法
查看>>
服务器负载粗略估算
查看>>
Spring 中 ApplicationContext 和 BeanFactory 的区别
查看>>
3.28Day09函数
查看>>
Linux Makefile 生成 *.d 依赖文件及 gcc -M -MF -MP 等相关选项说明【转】
查看>>
Linux下安装Python-3.3.2【转】
查看>>
npm
查看>>