讨论深拷贝与浅拷贝之前,要先回顾一下值传递与引用传递:

值传递:
var a = 10;
var b = a;
b++;
//console.log(a,b)//a:10 b:11

引用传递:
var arr = [10,20,30,40];
var arr1 = arr;
arr1[0] = 40;
//console.log(arr,arr1);//[40,20,30,40] [40,20,30,40]

一、浅拷贝(引用传递)

(1)概念

浅拷贝:

当一个对象拷贝另一个对象的数据的时候,
只要一个对象的数据发生改变另一个对象的数据也会发生改变

因为浅拷贝拷贝的是引用的地址,
(所以必须在对象是多层才能拷贝,单层拷贝的是数值,多层说明里面套着对象,所以拷贝的是地址。)

(2)实现方式

方法一(ES6的方法):

Object.assign()  作用:将第二个参数及以后的参数合并到第一个对象里。
参数1:target
参数2:对象......
参数3:对象....
//这个方法只会拷贝一层!不会拷贝第二层!

例: 
 var obj = {a:{name:"kaiqin",age:19}};
 var obj1 = Object.assign({},obj);
 obj1.a.name="wang"
 console.log(obj1)//{a: {name: "wang", age: 19}}
 console.log(obj)//{a: {name: "wang", age: 19}}

方法二:使用  for  in 循环,遍历每一个属性,将他们赋值给新的对象。 
要求对象必须是多层的状态下才能实现浅拷贝
var obj = { a: {name:"kaiqin",age:19 } } ;

function copy(obj){
 var newObj = {};
 for(var key in obj){
 newObj[key] = obj[key];
 }
return newObj;
}
var obj1 = copy(obj);
obj1.a.name="wang"
console.log(obj1)//a: {name: "wang", age: 19}
console.log(obj)//a: {name: "wang", age: 19}

方法三:$.extend()
 除了可以给jquery对象扩展方法外还可以实现深浅拷贝
 1、布尔值 如果填true的情况下是深考贝 什么也不写就是浅拷贝
 2、目标对象、数组
 3......后面所有的对象 都是需要合并的对象

var obj = {a:{name:"kaiqin",age:19}};
var obj1 = {b:{name:"wang",age:19}};
var obj2 = $.extend({},obj,obj1)
obj2.a.name="zhang";
console.log(obj2)
//{a: {name: "zhang", age: 19},b: {name: "wang", age: 19}}
console.log(obj)
//{a: {name: "zhang", age: 19}}

二、深拷贝

(1)概念

当一个对象拷贝另一个对象的数据的时候,
其中一个对象的数据发生变化不会影响另一个对象的数据
因为深考贝拷贝的是对象的数据而不是地址

(2)实现方法

方法一:对象是单层的情况下
Object.assign()//这个只拷贝一层,再来一层就废了 如上
var obj = {a:1,b:2,c:3}
var obj1 = Object.assign({},obj);
obj1.a = 30;
console.log(obj1,obj)
//obj1==>{a:1,b:2,c:3}
//obj==>{a:30,b:2,c:3}

方法二:差不多比较完美
$.extend()
 除了可以给jquery对象扩展方法外还可以实现深浅拷贝
 1、布尔值 如果填true的情况下是深考贝 什么也不写就是浅拷贝
 2、目标对象
 3......后面所有的对象 都是需要合并的对象
var obj = {a:{name:"kaiqin",age:19}};
var obj1 = {b:{name:"wang",age:19}};
var obj2 = $.extend(true,{},obj,obj1);
obj2.a.name="zhang";
console.log(obj2)
//{a: {name: "zhang", age: 19},b: {name: "wang", age: 19}}
console.log(obj)
//{{a:{name:"kaiqin",age:19}}}

方法三:JSON.parse、JSON.stringfiy      
不能拷贝函数,但用在拷贝数据库数据时,不影响。
因为数据库没有函数。所以推荐使用

其原理是:先将对象转换为字符串、再转换成对象,
此时地址一定发生了变化,所以可以实现浅拷贝。

var obj1 = {b:{name:"wang",age:19}};

var obj2 = JSON.parse(JSON.stringify(obj1));   //此时地址发生了改变。

obj2.b.name = "kaiqin";

console.log(obj1,obj2)

slice和concat对对象数组的拷贝,整个拷贝还是浅拷贝,拷贝之后数组各个值的指针还是指向相同的存储地址。
因此,slice和concat这两个方法,仅适用于对不包含引用对象的一维数组的深拷贝
使用slice和concat对数组的深拷贝和浅拷贝:链接


南山不会落梅花
49 声望3 粉丝