在项目中使用object.assign克隆对象的时候,原意不改变原对象,但是实际效果改变了,遂查阅了一下资料,整理一下object.assign的用法以及深浅拷贝的问题.
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
语法:Object.assign(target, ...sources)
target:目标对象; sources:源对象
返回值:目标对象注意:如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。
使用场景:
1.克隆一个对象:
const obj = {
a: 1
};
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
2.为对象构造属性
/***
* 构造树的数据
* @param data 输入数据
*/
createTreeData(data: any[]) {
data.forEach(item => {
const extra = {
title: item.moduleName,
key: item.id,
isLeaf: !item.children.length
};
Object.assign(item, extra);
if (!extra.isLeaf) {
this.createTreeData(item.children);
}
});
}
3.合并对象
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };
const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。
4.合并具有相同属性的对象
const o1 = {
a: 1,
b: 1,
c: 1
};
const o2 = {
b: 2,
c: 2
};
const o3 = {
c: 3
};
const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
深浅拷贝问题:
我们先看一个例子:
let obj1 = {
a: 1,
b: {
c: {
d: 0
}
}
};
let obj2 = Object.assign({}, obj1)
let obj3 = JSON.parse(JSON.stringify(obj1));
obj1.a = 2;
console.log(obj1.a) //2
console.log(obj2.a) //1
console.log(obj3.a) //1
obj1.b.c.d = 1;
console.log(obj1.b.c.d); //1
console.log(obj2.b.c.d); //1
console.log(obj3.b.c.d); //0
我们发现:当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。
因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用。
深浅拷贝总结:
- 在针对深拷贝的问题,建议使用Json.parse(Json.stringfy(obj)),用 JSON.stringify 把对象转换成字符串,再用 JSON.parse 把字符串转换成新的对象。 注意:可以转成 JSON 格式的对象才能使用这种方法,如果对象中包含 function 或 RegExp 这些就不能用这种方法了.
- 深拷贝在项目中,我们也可以借助第三方库(lodash.cloneDeep),或者自己写一个递归来进行实现.
网友评论