对象的深拷贝和浅拷贝
完全赋值or引用
对象的浅拷贝
对象的浅拷贝,相当于地址的引用,这样拷贝出来的对象会随着原始对象的改变而改变。
例子如下:
var obj = {name:'zhangsan',age:18}
var newObj = obj;
var newObj2 = Object.assign(obj,true);
console.log(obj,newObj,newObj2);
obj.age = 20;
console.log(obj,newObj,newObj2)
结果如下:
对象的深拷贝
var obj={name:'zhangsan',age:18}
function copyObject(Target, Origin) {
var Target = Target || {};
for (const key in Origin) {
if (Origin.hasOwnProperty(key)) {
//判断为对象类型,数组也属于对象类型
if (Origin[key] !== null && typeof (Origin[key]) == "Object") {
if (Object.prototype.toString.call(Origin[key]) == "[Object Array]") { //call方法表示调用
Target[key] = [];
} else {
Target[key] = {};
}
copyObject(Target[key], Origin[key]);
} else {
Target[key] = Origin[key];
}
}
}
}
var newobj = {};
copyObject(newobj,obj);
console.log(newobj,obj);
结果如下
这里修改了obj的age,newobj没有跟着变化,说明这两个对象已经不指向同一块内存了
如果对象可以转为JSON,也可以使用JSON中提供的方法进行深度拷贝。
JSON.stringify(obj); //将对象序列化成 一个JSON 字符串的值。
JSON.parse(json); //将一个JSON字符串转为对象。
var newObj = JSON.parse(JSON.stringify(obj));
这样也可以达到上边的效果,但是存在一定的局限性。必须为json格式的对象。
相关问题的联系
这里有这样一个问题,展开一个对象中的数组,传入参数为要展开的对象。
var a = {a:[1,2,3],b:[4,5,6],c:‘aaaaa’}
通过一个函数将对象展开,变成 {a:1,b:[4,5,6],c:‘aaaaa’},{a:2,b:[4,5,6],c:‘aaaaa’},{a:3,b:[4,5,6],c:‘aaaaa’},并将结果放入数组。
分析:拿到这个问题,首先想到获取到参数对应的数组。然后循环数组,修改数组中该变量的值,然后将修改后的对象放入数组中,这样但是实际代码写下来,你会发现自己的结果不对,三个对象一毛一样。这里就涉及到对象的拷贝了,数组中放入的是同一个对象,对象改变了,指向这个地址的所有对象都会改变。所以数组里会是三个相同的对象。
所以我们需要将每次的对象复制出来,在放到数组中。这样数组里的每个对象都是独立的。
var a = {a:[1,2,3],b:[4,5,6],c:1};
function unwind(a,b){
var arr = a[b];
debugger;
var newArr = [];
arr.forEach(element => {
var json = JSON.stringify(a);
var newObj = JSON.parse(json);
newObj[b]=element;
newArr.push(newObj);
});
console.log(newArr);
}
unwind(a,'a');
结果如下: