JS的浅拷贝和深拷贝
JS浅拷贝和深拷贝在平时工作中可能不是很在意,但是相信大家都知道 Vue.js 和 react.js 等框架,这里面的 state 、 props 处理的时候就涉及到这个拷贝,这些框架都是数据驱动视图,也就是说数据模型的变更相应的页面视图也会改变,试想一下,如果后台返回的数据是一个多级的对象,而你只是对它浅拷贝和其他处理后用在多处地方,当这个拷贝对象深层级做了变更后,原对象的深层级其实也一样变更了,这就不是我们想要的。比如下面这个例子:
1 | let obj = { |
然后我们对其实行浅拷贝,实现浅拷贝有下面两种方式:
1 | // ES6 |
此时我们在控制台打印出来,并看不出什么问题,我们在控制台做进一步处理,对拷贝的对象的第三层的 x 属性做更改,
1 | obj2.c.x = 123; |
我们发现,obj 和 obj2 的 x 属性都发生了变更,究其原因,是因为浅拷贝只是拷贝它的第二级数据,对于复杂类型的拷贝就只是拷贝它的引用,也就是地址,在上面案例中也就是 obj 和 obj2 它们的 c 属性都指向同一个地址,而这个地址所存储的是一个对象,当对象被修改,自然地另一个引用也会变更,如何来解决这个问题呢?我们就需要使用到深克隆。
1 | let obj2 = JSON.parse(JSON.stringify(obj)); |
我们使用了 JSON 对象所提供的方法把原对象转换为字符串,然后再转成 json 对象,这样可以很简单的实现大部分常规对象的深拷贝,但是存在弊端,会发现对象中的正则在转成字符串的时候是一个空对象,不仅仅是正则,还有 null 、 Date 和 Function 也会改变,所以需要通过遍历来封装一个深拷贝函数,然后对这几种特殊的类型特殊处理。
1 | function deepClone(obj){ |
然后,我们可以深层次判断克隆对象是否和原有对象相等了,结果显然,它们不是同一个东西。
1 | let obj2 = deepClone(obj); |