【修真院web小课堂】 如何实现数组深拷贝和浅拷贝
大家好,我是IT修真院西安分院第1期的学员,一枚正直纯洁善良的WEB程序员,
1.知识剖析
js有深拷贝和浅拷贝的区别,
js中的两种变量类型, 即值类型(数值、布尔值、null、undefined) 和引用类型(对象、数组、函数)。值类型保存于栈中,而引用类型保存在堆中。值类型和引用类型赋值时的不同, 值类型赋值时会在内存中开辟一块新的空间,然后把赋过来的值保存于这块新开辟的空间中,引用类型赋值时也会开辟一块新的空间,不同的时新的空间保存的是赋值对象虽在的地址(即浅拷贝,也就是说赋值和被赋值对象引用的是同一个对象,所以改变其中任何一个对象时,另一个会随之改变)。所以深拷贝和浅拷贝概念只针对于引用类型,对于值类型来说没有意义。
复制的时候相当于复制引用地址
浅拷贝:相当于使两个数组指针指向相同的地址,任一个数组元素发生改变, 影响另一个。
深拷贝:两数组指针指向不同的地址,数组元素发生改变时不会相互影响。
2.常见问题
3.解决问题
浅拷贝:
深拷贝:
除了js 里面的slice(), concat() , 以及jq里面的extend()都可以实现深拷贝
jQuery.extend([deep], target, object1, object2, object3...),
[deep]:默认false【不能显式设置为false;值为true时深度合并对象。
target:其他对象复制到该对象
object:被合并的对象
arrayObject.slice(start,end)
tart 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
end 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。
concat()
rrayObject.concat(arrayX,arrayX,......,arrayX)
arrayX 必需。该参数可以是具体的值,也可以是数组对象。可以是任意多个。
二维数组
浅拷贝
深拷贝
如果对象obj
拷贝情况
浅拷贝:只拷贝对象的第一层属性,对于属性中包含的属性不会复制;
由于JavaScript对象均以地址的方式存贮,
所以浅复制导致多个对象的属性均指向同一块地址。
深拷贝:对对象的每一层属性进行递归复制,
深层次的属性也不会指向同一块地址【同一个对象】。
运行结果:由于对象的浅拷贝只复制第一层属性,
因此obj b第一层属性的改变不会影响复制源,
而第二层属性仍指向同一块地址,
因此obj b的dance属性的today属性作改变之后,
同一块地址处的obj a的dance属性的today属性同时变化了。
浅拷贝
深拷贝
4.解决问题
5.编码实战
6.扩展思考
7.参考文献
参考一:http://larry850806.github.io/2016/09/20/shallow-vs-deep-copy/
[Javascript] 關於 JS 中的淺拷貝和深拷貝
参考二:http://jerryzou.com/posts/dive-into-deep-clone-in-javascript/
深入剖析JavaScript 的深复制
问题1:
什么叫深拷贝 浅拷贝?
答:浅拷贝:相当于使两个数组指针指向相同的地址,任一个数组元素发生改变, 影响另一个。
深拷贝:两数组指针指向不同的地址,数组元素发生改变时不会相互影响。
问题2:
除了递归,我们还可以借用JSON对象的parse和stringify?
问题3:
深拷贝和浅拷贝的区别?
答:浅复制 —-只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。
深复制 —-在计算机中开辟了一块新的内存地址用于存放复制的对象。