深拷贝指的是对象属性所引用的对象全部进行新建对象复制,以保证深复制的对象的引用图不包含任何原有对象或对象图上的任何对象,隔离出两个完全不同的对象图。
例如,我们要将 b.obj 复制到 a 中,
浅拷贝仅仅只是复制引用(Reference),拷贝后,a.obj === b.obj
深拷贝是创建(clone)了一个一模一样的对象,并保存在a.obj中,所以 a.obj !== b.obj
代码层面实现深浅复制
数组拷贝
1 | // 浅复制, 双向改变, 指向同一块内存区域 |
不考虑特殊情况的对象复制
1 | // 知乎看到的深复制方法,这个函数可以深拷贝 对象和数组,很遗憾,对象里的函数会丢失 |
第三方库实现深浅复制
1. jQuery: $.extend
$.extend方法第一个参数可以是布尔值, 用来设置是否深度拷贝
1 | jQuery.extend(true, { a : { a : "a" } }, { a : { b : "b" } } ); |
下面是源码:
1 | jQuery.extend = jQuery.fn.extend = function() { |
2. Underscore: _.clone()
在 Underscore 中有这样一个方法:_.clone(),这个方法实际上是一种浅复制 (shallow-copy),所有嵌套的对象和数组都是直接复制引用而并没有进行深复制。
3. loadsh: _.clone()
/ _.cloneDeep()
在lodash中关于复制的方法有两个,分别是_.clone()
和_.cloneDeep()
。
其中_.clone(obj, true)
等价于_.cloneDeep(obj)
。
使用上,lodash和前两者并没有太大的区别,但看了源码会发现,Underscore 的实现只有30行左右,而 jQuery 也不过60多行。可 lodash 中与深复制相关的代码却有上百行.
这是因为jQuery 无法正确深复制 JSON 对象以外的对象,
而 lodash 花了大量的代码来实现 ES6 引入的大量新的标准对象。