对象的深拷贝和浅拷贝
2017-06-21 本文已影响0人
颠倒的黑白
数组的深浅拷贝
在使用JavaScript对数组进行操作的时候,我们经常需要将数组进行备份,事实证明如果只是简单的将它赋予其他变量,那么我们只要更改其中的任何一个,然后其他的也会跟着改变,这就导致了问题的发生。
浅拷贝
var arr = ["One","Two","Three"];
console.log(arr);//["One", "Two", "Three"]
var arrto = arr;
arrto[1] = "test";
console.log("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,test,Three
console.log("数组的新值:" + arrto + "<br />");//Export:数组的新值:One,test,Three
像上面的这种直接赋值的方式就是浅拷贝,很多时候,这样并不是我们想要得到的结果,其实我们想要的是arr的值不变,不是吗?
深拷贝
方法一:js的slice函数
var arr = ["One","Two","Three"];
var arrtoo = arr.slice(0);
arrtoo[1] = "set Map";
document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,Two,Three
document.writeln("数组的新值:" + arrtoo + "<br />");//Export:数组的新值:One,set Map,Three
方法二:js的concat方法
var arr = ["One","Two","Three"];
var arrtooo = arr.concat();
arrtooo[1] = "set Map To";
document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,Two,Three
document.writeln("数组的新值:" + arrtooo + "<br />");//Export:数组的新值:One,set Map To,Three
Obj的深浅拷贝
直接引用,修改了原对象
let conf = {
adapter:'sqlite',
db: {
sqlite:{
name:'xxx.sqlite'
},
mysql:{
name:'xxx',
username:'work',
passwd:'******'
}
}
}
//直接引用
let conf2 =conf;
conf2.adapter = 'mysql';
console.log(conf);
console.log(conf2)
浅拷贝
let conf = {
adapter:'sqlite',
db: {
sqlite:{
name:'xxx.sqlite'
},
mysql:{
name:'xxx',
username:'work',
passwd:'******'
}
}
}
//浅拷贝
let copied = Object.assign({},conf);
copied.adapter = 'mysql';
console.log(conf.adapter);//"sqlite"
console.log(copied.adapter);//"mysql"
copied.db.sqlite.name ='yyy.sqlite';
//多级属性无法被拷贝,而是引用
console.log(conf.db.sqlite.name);//"yyy.sqlite"
console.log(copied.db.sqlite.name);//"yyy.sqlite"
所以使用深拷贝
let conf = {
adapter:'sqlite',
db: {
sqlite:{
name:'xxx.sqlite'
},
mysql:{
name:'xxx',
username:'work',
passwd:'******'
}
}
}
//深拷贝
function deepCopy(des,src) {
for(var key in src) {
let prop = src[key];
if (typeof prop === 'object') {
des[key] = des[key]||{}; //判断目标对象是否有自身的key
deepCopy(des[key],prop);
}else{
des[key] = src[key];
}
}
return des;
}
let obj1= {
db:{
c:"name"
},
ad:'ad'
}
let deepCopied = deepCopy(obj1,conf);
let deepCopied2= deepCopy({},conf);
console.log(deepCopied);
console.log(deepCopied2);
deepCopied.db.sqlite.name = 'zzz.sqlite';
console.log([deepCopied.db.sqlite.name,conf.db.sqlite.name]);
//console
[object Object] {
ad: "ad",
adapter: "sqlite",
db: [object Object] {
c: "name",
mysql: [object Object] { ... },
sqlite: [object Object] { ... }
}
}
[object Object] {
adapter: "sqlite",
db: [object Object] {
mysql: [object Object] { ... },
sqlite: [object Object] { ... }
}
}
["zzz.sqlite", "xxx.sqlite"]