浅拷贝深拷贝对象的几种方法及区别
前言
总结拷贝对象的方法及浅拷贝和深拷贝的区别
一、浅拷贝
被拷贝对象有第二层或多层嵌套对象的时候,对里层的对象只拷贝了内存地址,里层嵌套的对象数据发生变化时,拷贝出来的对象也会发生改变,对于其他的基本类型不会发生变化
1、方法1
js原生赋值方法
代码如下(示例):
var obj={
userNeme:"xiaoming",
age:20
}
var obj1=obj;
obj.phone=12356564;
console.log(obj);//{userNeme:"xiaoming",age:20,phone:12356564};
console.log(obj1);//{userNeme:"xiaoming",age:20,phone:12356564};
此时无论是obj还是obj1的任何一个数据发生变化时,两者都会发生变化,因为此时两者是共用的同一个内存地址。
这种方法相当于一种浅层次的拷贝,两者共用一个内存,两者的数据相互影响
2、方法2
js原生for in方法
代码如下(示例):
var obj={
userNeme:"xiaoming",
age:20,
obj2:{
email:"54648468@qq.com"
}
}
var obj1 = {};
for(var item in obj){
obj1[item]=obj[item]
};
obj.phone=12356564;
obj.obj2.address="河南";
console.log(obj);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com", address: "河南"}, phone: 12356564}
console.log(obj1);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com", address: "河南"}}
此时obj中的obj2的数据发生变化时,obj1中的obj2的数据也会发生变化,因为此时两者是相同的内存地址;
obj中的简单类数据发生变化时不会影响到obj1中的简单类数据,obj和obj1的内存地址是不同的。
3、方法3
使用ES6中的拓展运算符
代码如下(示例):
var obj={
userNeme:"xiaoming",
age:20,
obj2:{
email:"54648468@qq.com"
}
}
var obj1 = { ...obj };
obj.phone=12356564;
obj.obj2.address="河南";
console.log(obj);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com", address: "河南"}, phone: 12356564}
console.log(obj1);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com", address: "河南"}}
此时obj中的obj2的数据发生变化时,obj1中的obj2的数据也会发生变化,因为此时两者是相同的内存地址。
obj中的简单类数据发生变化时不会影响到obj1中的简单类数据,obj和obj1的内存地址是不同的。
4、方法4
使用ES6中Object的assign方法
代码如下(示例):
var obj={
userNeme:"xiaoming",
age:20,
obj2:{
email:"54648468@qq.com"
}
}
var obj1 = Object.assign({},obj);
obj.phone=12356564;
obj.obj2.address="河南";
console.log(obj);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com", address: "河南"}, phone: 12356564}
console.log(obj1);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com", address: "河南"}}
此时obj中的obj2的数据发生变化时,obj1中的obj2的数据也会发生变化,因为此时两者是相同的内存地址。
obj中的简单类数据发生变化时不会影响到obj1中的简单类数据,obj和obj1的内存地址是不同的。
二、深拷贝
1、方法1
使用JSON字符串的方法
代码如下(示例):
var obj={
userNeme:"xiaoming",
age:20,
obj2:{
email:"54648468@qq.com"
},
ignore:undefined,
ignoreFunction(){
console.log(345);
}
}
var obj1 = JSON.parse(JSON.stringify(obj))//会忽略掉对象obj里面的undefined和函数
obj.phone=12356564;
obj.obj2.address="河南";
console.log(obj);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com", address: "河南"}, ignore: undefined, ignoreFunction: ƒ, …}
console.log(obj1);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com"}}
此时obj中的obj2的数据发生变化时,obj1中的obj2的数据不会发生变化,因为此时两者是不同的内存地址。
obj中的简单类数据发生变化时不会影响到obj1中的简单类数据,obj和obj1的内存地址是不同的。
需要注意的是: 这个方法在拷贝对象时 ,如果对象里面的属性值含有undefined和函数的话会被忽略掉,无法拷贝到新的对象中,这是由于JSON的特性导致的,JSON字符串在转化为JSON对象的时候会自动忽略掉undefined和函数
2、方法2
使用递归的方法
代码如下(示例):
var obj = {
userNeme: "xiaoming",
age: 20,
obj2: {
email: "54648468@qq.com"
},
ignore: undefined,
ignoreFunction: function () {
console.log(345);
}
}
function deepCopy(copyobj){
var obj1=Array.isArray(copyobj)?[]:{}
for(var item in copyobj){
if(typeof copyobj[item]=="object"){
obj1[item]=deepCopy(copyobj[item])
}else{
obj1[item]=copyobj[item]
}
}
return obj1
}
let newobj=deepCopy(obj)//obj2中的内容无法拷贝出来
obj.phone = 12356564;
obj.obj2.address = "河南";
console.log(obj);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com", address: "河南"}, ignore: undefined, ignoreFunction: ƒ, …}
console.log(obj1);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com"}, ignore: undefined, ignoreFunction: ƒ}
此时obj中的obj2的数据发生变化时,obj1中的obj2的数据不会发生变化,因为此时两者是不同的内存地址。
obj中的简单类数据发生变化时不会影响到obj1中的简单类数据,obj和obj1的内存地址是不同的。
3、方法3
使用jQuery的extend方法
代码如下(示例):
var obj = {
userNeme: "xiaoming",
age: 20,
obj2: {
email: "54648468@qq.com"
},
ignore: undefined,
ignoreFunction: function () {
console.log(345);
}
}
var obj1={};
$.extend(true,obj1, obj);
obj.phone = 12356564;
obj.obj2.address = "河南";
// true为深拷贝(false为浅拷贝) 省略时默认为false,obj1为要扩展的对象,后边的就是扩展的内容,可以有多个
// 扩展的内容可以识别函数,不能识别undefined
console.log(obj);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com", address: "河南"}, ignore: undefined, ignoreFunction: ƒ, …}
console.log(obj1);//{userNeme: "xiaoming", age: 20, obj2: {email: "54648468@qq.com"}, ignoreFunction: ƒ}
此时obj中的obj2的数据发生变化时,obj1中的obj2的数据不会发生变化,因为此时两者是不同的内存地址。
obj中的简单类数据发生变化时不会影响到obj1中的简单类数据,obj和obj1的内存地址是不同的。
需要注意的是: 这个方法在拷贝对象时 ,扩展的内容可以识别函数,不能识别undefined