ES6 能否使用Object.assign实现深浅拷贝?
答案:当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。
看例子:
1 普通变量
let obj={name:"zhangsan",colors:["red", "green", "blue"]};
let obj2=Object.assign({},obj);
obj2.name='wang';
console.log(obj2);//name wang colors:["red", "green", "blue"]
console.log(obj);//name zhangsan colors:["red", "green", "blue"]
结论:普通变量拷贝可以使用Object.assign
2 引用变量
let obj={name:"zhangsan",colors:["red", "green", "blue"]};
let obj2=Object.assign({},obj);
obj2.colors[0]='orange';
console.log(obj2);//name zhangsan colors:["orange", "green", "blue"]
console.log(obj);//name zhangsan colors:["orange", "green", "blue"]
结论:Object.assign对于含有引用类型值的对象无法深拷贝。
3 数组
3.1 普通数组
let colors = ['red','green','blue'];
let colors2 = Object.assign([],colors);
colors2[0] = "orange";
console.log(colors2);//['orange','green','blue']
console.log(colors);//['red','green','blue']
结论:普通数组拷贝可以使用Object.assign
3.2 含有引用类型的值的数组
let colors=['red','green','blue',['football','basketball','volleyball']];
let colors2=Object.assign([],colors);
colors2[3][0]="ping-pang";
console.log(colors2);//['red','green','blue',['ping-pang','basketball','volleyball']]
console.log(colors);//['red','green','blue',['ping-pang','basketball','volleyball']]
结论:和上面一样,如果一维数组里面有引用类型的值,则无法深拷贝。
如何实现深拷贝?
1 数据结构中不包含引用类型
使用Object.assign()
,{...obj}
等效
2020-02-16补充:
引用类型对象的值属于"普通"对象,可以使用{...obj}实现深拷贝,比如
let _o = { a: [1,2,3], b: function(){return 1}, c: [1,5]};
let o = { ..._o };
// 下面两种修改不会改变_o对象
o.a = [2,2,2];
o.b = function(){return 2};
_o.a; // [123]
_o.b(); // 1
引用类型对象的值属于"引用类型"对象,则不可以使用{...obj}实现深拷贝,比如
let _o = { a: [1,2,3], b: function(){return 1}, c: [1,[3,3,3]]};
let o = { ..._o };
o.c[1] = [4,4,5];
_o.c; // [1,[4,4,5]]
只包含一层引用的情况可以使用{...obj}实现深拷贝
2 数据结构中包含引用类型,符合JSON规则(不包含functon)
直接使用:JSON.parse(JSON.stringify({xxx:'xxx}))
,简单粗暴~~~~ .
3 数据结构中既有引用类型,又有function
1 通过jQuery的extend方法实现深拷贝,但是估计较少人使用jQuery了
2 lodash.cloneDeep()实现深拷贝
let obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
let obj2 = _.cloneDeep(obj1);
3 使用递归的方式实现深拷贝
function _deepClone(source) {
let target;
if (typeof source === 'object') {
target = Array.isArray(source) ? [] : {}
for (let key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] !== 'object') {
target[key] = source[key]
} else {
target[key] = _deepClone(source[key])
}
}
}
} else {
target = source
}
return target
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。