警告
看完文章,可能会颠覆你的认知!!
语法
Object.assign(target, ...sources)
错误示范
我们都知道Object.assign()可以实现对象拷贝,很多人认为他只能实现浅拷贝,我翻遍了MDN的文档,也没搜索到一个浅字。
那么,到底什么是深拷贝、什么是浅拷贝,你可以去搜索其他文章看看。
下面给大家展示一个错误使用Object.assign的例子(希望原作者看到别打我,我已经写上转载来源了?)
let obj = { name: ‘程序猿‘, age:{child: 12} }
let copy = Object.assign({}, obj);
copy.name = ‘单身狗‘
copy.age.child = 24
console.log(obj) // { name: ‘程序猿‘, age:{child: 24} }
作者:拌着生活
链接:https://www.jianshu.com/p/70dc5b968767
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
上面的例子大概是这个意思,有一个原始的obj对象,他里面的age对象有一个子节点child,然后使用Object.assign({}, obj)直接拷贝这个对象(或者叫做浅拷贝obj),最后用点赋值法修改copy对象的属性,结果是对原obj对象也进行了修改。
老天,Object.assign怎么这么烂,说好的拷贝呢,只是浅拷贝啊,那react中是不是一大堆state都是N层结构的对象,不能用Object.assign来玩了呢?
来分析一下它错在哪里了。
从语法上来说,并没有用错,的确,这样能实现对象的拷贝,或者叫做“浅拷贝”,但是,如果要修改对象里面的属性,就需要用到“对象的合并”,也就是下面将要讲到的。其实MDN上讲的很明白,Object.assign应该怎样用,只是大家习惯了看博客。
正确使用
看了错误示范,不用担心,我带你来正确使用Object.assign。
我也定义一个对象obj。
let obj = {name: ‘二月‘, age: {c: 12}}
正确使用Object.assign进行对象的拷贝,通常有2种方式。
1、Object.assign()
我们对要修改的内部对象属性进行单独的赋值,既不修改obj,也不修改新对象o2,定义单独的age。还记得文章开头的语法吗,源对象...sources表示支持多个散列的对象。
下面的做法相当于,我们定义了一个新的age对象,将它和obj对象进行合并,然后拷贝给一个空对象{},这样使用Object.assign(),就不会对原对象obj产生影响。
let age = {c: 88}
let o2 = Object.assign({}, obj, {age})
console.log(obj, o2)
那么,有人可能会质疑了,它只是浅拷贝啊,就算你取巧实现了拷贝,但是要是对o2进行赋值了咋办,不也一样会改变obj的值?
相信我,不会的,别被网上所谓的“浅拷贝”迷惑了你的眼睛。
我紧接着对o2里面的age进行直接的赋值,打印出来的obj仍旧不受影响,是不是很神奇!!
let obj = {name: ‘二月‘, age: {c: 12}}
let age = {c: 88}
let o2 = Object.assign({}, obj, {age})
o2.age.c = 66
console.log(obj, o2)
2、ES6的扩展运算符
现在我们都喜欢用ES6的扩展运算符来替换Object.assign。
let obj = {name: ‘二月‘, age: {c: 12}}
let o1 = {...obj, age: {c: 88}}
console.log(obj, o1)
同样的,我把o1也用点语法重新赋值看看会不会对obj产生影响,答案当然是不会!
let obj = {name: ‘二月‘, age: {c: 12}}
let o1 = {...obj, age: {c: 88}}
o1.age.c = 99
console.log(obj, o1)
3、分析原理
一切都要从语法说起Object.assign(target, ...sources),第一个参数target决定了你的对象被拷贝到哪个目标对象上面,如果你不想对原始对象产生影响,就定义一个空对象{}作为target,单单这样还不够,sources只设置原始对象obj的话,表示对原始对象的“浅拷贝”,但是设置多个对象的合并,就会返回一个全新的对象。
总结
看了这篇文章,你摸着良心问问自己,真的理解什么是Object.assign和扩展运算符了吗?更深一个层次来看,你真的理解什么是浅拷贝、什么是深拷贝了吗??
补充:纠结age的人是不是没有写过reducer啊,这是一种用assign合并对象的思想,age对象是否变化根本就不是要关心的事情。