js 中经常用到对象的浅拷贝与深拷贝。下面来对它们作一个探讨。
什么是拷贝?浅拷贝与深拷贝的区别是什么?
拷贝就是生成对象的一个一模一样的副本,就像文件的复制一样。JavaScript 中的拷贝就是生成跟原对象一模一样的对象。
JavaScript 中的数据类型分为简单类型(boolean, string, number, undefined, null)
和复杂类型(Function、Array、Object)。简单类型是按值存储的,复杂类型是按引用存储的。
浅拷贝与深拷贝对简单类型的处理是一致的,但对复杂类型有区别,浅拷贝只拷贝复杂类型的引用,
拷贝后的对象跟原对象引用同一块内存空间。
深拷贝则对拷贝的对象重新分配存储空间,拷贝后的对象跟原对象引用不同的内存空间。
浅拷贝实现方法
Object.assign
1 | Object.assign(target, ...sources); |
Object.assign 将源对象自身的且可枚举的属性拷贝到 target。
Object.assign 使用源对象的的[[get]]
和目标对象的[[set]]
方式进行拷贝,这意味着
它会触发属性的 getters 和 setters。所以拷贝 get 描述的属性时需只会拷贝值,不会拷贝定义。
通过Object.getOwnPropertyDescriptor()
和 Object.defineProperty()
来解决。
更多 Object.assign 请参考: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
简单复制语句
1 | function simpleClone(sourceObj){ |
深拷贝实现方法
利用 JSON 内置对象
1 | function deepClone (obj){ |
优缺点:
- 他无法实现对函数 、RegExp等特殊对象的克隆
- 会抛弃对象的constructor,所有的构造函数会指向Object
- 对象有循环引用,会报错
递归拷贝
1 | function deepClone (targetObj, srcObj){ |
// 深克隆还有很多坑待解决,上面的还不够 TODO…