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

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

所谓 
深浅拷贝
对于仅仅是复制了引用(地址),换句话说,复制了之后,原来的变量和新的变量指向同一个东西,彼此之间的操作会互相影响,为 
浅拷贝
而如果是在堆中重新分配内存,拥有不同的地址,但是值是一样的,复制后的对象与原来的对象是完全隔离,互不影响,为 
深拷贝
 
深浅拷贝 的主要区别就是:复制的是引用(地址)还是复制的是实例。
1 //浅复制 2 function shallowCopy(src){ 3     var dst = {}; 4     for(var key in src){ 5         if(src.hasOwnProperty(key)){ 6             dst[key] = src[key]; 7         } 8     } 9     return dst;10 }11 12 var obj = {13     a : 1,14     arr : [2,3]15 };16 var shallowObj = shallowCopy(obj);17 console.log(obj === shallowObj);   //false18 shallowObj.arr[1] = 5;19 console.log(obj.arr[1]);   // = 520 console.log(obj);         //{ a: 1, arr: [ 2, 5 ] }21 console.log(shallowObj);  //{ a: 1, arr: [ 2, 5 ] }
//利用 递归 来实现深复制,对属性中所有引用类型的值,遍历到是基本类型的值为止。function deepCopy(src){    if(!src && typeof src !== 'object'){        return;    }    var dst = src.constructor  === Array ? []:{};    for(var key in src){        if(src.hasOwnProperty(key)){            if(src[key] && typeof src[key] === 'object'){                dst[key] = src[key].constructor === Array ? []:{};                dst[key] = deepCopy(src[key]);   //递归            }else{                dst[key] = src[key];            }        }    }    return dst;}var a = {    name:"jack",    age:20};var b = deepCopy(a);console.log(a === b);   //falsea.age = 30;console.log(a);     //{ name: 'jack', age: 30 }console.log(b);     //{ name: 'jack', age: 20 }

 深拷贝浅拷贝问题探究:

1. Array 的 slice 和 concat 方法

两者都会返回一个新的数组实例。

//slicevar a = [1,2,3];var b = a.slice(); //slice    console.log(b === a);a[0] = 4;    console.log(a); //[ 4, 2, 3 ]    console.log(b); //[ 1, 2, 3 ]//concatvar a = [1,2,3];var b = a.concat();  //concat    console.log(b === a);a[0] = 4;    console.log(a);  //[ 4, 2, 3 ]    console.log(b);  //[ 1, 2, 3 ]

看起来很像深拷贝,但实际上不是!!!

//slicevar a = [[1,2,3],4,5];var b = a.slice();    console.log(a === b); //falsea[0][0] = 6;    console.log(a);   //[ [ 6, 2, 3 ], 4, 5 ]    console.log(b);   //[ [ 6, 2, 3 ], 4, 5 ]//concatvar a = [[1,2,3],4,5];var b = a.concat();  //concat    console.log(b === a); //falsea[0][0] = 6;    console.log(a);  //[ [ 6, 2, 3 ], 4, 5 ]    console.log(b);  //[ [ 6, 2, 3 ], 4, 5 ]

 Array的 slice 和 concat 方法 并不是 真正的深拷贝,他们其实是浅拷贝。   递归复制是无法完成的。

2. jQuery中的 extend 复制方法

可以用来扩展对象,这个方法可以传入一个参数:deep(true or false),表示是否执行深复制(如果是深复制则会执行递归复制)。

//jQuery环境下运行 //深复制 var obj = {    name:'xixi',    age:20,    company : { name : '腾讯', address : '深圳'} };var obj_extend = $.extend(true,{}, obj); //extend方法,第一个参数为true,为深拷贝,为false,或者没有为浅拷贝。console.log(obj === obj_extend);   //falseobj.company.name = "ali";obj.name = "hei";console.log(obj);  //{
name:'hei',age:20,company : { name : 'ali', address : '深圳'} } console.log(obj_extend); //{name:'xixi',age:20,company : { name : '腾讯', address : '深圳'} }
 
//jQuery环境下运行 //浅复制 var obj = {
name:"xixi",    age:20,    company : { name : '腾讯', address : '深圳'} };var obj_extend = $.extend(false,{}, obj); //extend方法,第一个参数为true,为深拷贝,为false,或者没有为浅拷贝。console.log(obj === obj_extend);   //falseobj.name = "heihei";console.log(obj);    //{
name:'heihei',age:20,company : { name : '腾讯', address : '深圳'} console.log(obj_extend); //{name:'xixi',age:20,company : { name : '腾讯', address : '深圳'}

总结:Array 的 slice 和 concat 方法 和 jQuery 中的 extend 复制方法,他们都会复制第一层的值,对于 第一层 的值都是 深拷贝,而到 第二层 的时候 Array 的 slice 和 concat 方法就是 复制引用 ,jQuery 中的 extend 复制方法 则 取决于 你的 第一个参数, 也就是是否进行递归复制。所谓第一层 就是 key 所对应的 value 值是基本数据类型,也就像上面栗子中的name、age,而对于 value 值是引用类型 则为第二层,也就像上面例子中的 company。

3. JSON 对象的 parse 和 stringify

JOSN 对象中的 stringify 可以把一个 js 对象序列化为一个 JSON 字符串,parse 可以把 JSON 字符串反序列化为一个 js 对象,这两个方法实现的是深拷贝

var obj = {    name:'xixi',    age:20,    company : { name : '腾讯', address : '深圳'} };var obj_json = JSON.parse(JSON.stringify(obj));console.log(obj === obj_json);   //falseobj.company.name = "ali";obj.name = "hei";console.log(obj);   //{ name: 'hei', age: 20, company: { name: 'ali', address: '深圳' } }console.log(obj_json);  //{ name: 'xixi', age: 20, company: { name: '腾讯', address: '深圳' } }

 

转载于:https://www.cnblogs.com/guorange/p/7137621.html

你可能感兴趣的文章
HDOJ-1013
查看>>
sudo: sorry, you must have a tty to run sudo
查看>>
【JBPM4】流程部署
查看>>
OneDrive网页版打不开的解决办法
查看>>
正则表达式-手机号
查看>>
Mac下使用Typora的一些简单操作
查看>>
python常用工具库介绍
查看>>
【转】android权限列表
查看>>
SMB横向利用
查看>>
cookie 和session 的区别详解
查看>>
文本处理命令
查看>>
HDU1241_广度优先搜索
查看>>
vim部分常用命令总结
查看>>
TensorFlow TensorBoard使用
查看>>
快速傅里叶变换(FFT)蝴蝶迭代
查看>>
【解题报告】BSOI2550 方格取数游戏 (转)
查看>>
为IEnumerable扩展一个ForEach方法
查看>>
面试题6:重建二叉树(前序遍历和中序遍历)
查看>>
(六)Oracle学习笔记—— 约束
查看>>
Node.js相关——CommonJS规范
查看>>