深浅拷贝
深拷贝与浅拷贝
- 浅拷贝
- 创建一个新对象,这个对象是原始对象属性的精确拷贝
- 对象的引用类型修改会相互影响
- 深拷贝
拷贝与赋值的区别
- 赋值赋的是对象在栈中的地址,而不是堆中的数据,对象间会相互影响
- 浅拷贝:重新在堆中创建内存,基本数据类型不会相互影响,但引用类型会相互影响
- 深拷贝:对对象中的子对象进行递归拷贝,拷贝的两个对象互不影响
实现方式
- 浅拷贝的实现方式
- Object.assign()
let obj2 = Object.assign({}, obj1)
- ...
- concat
- lodash clone
var newObject = $.extend({}, oldObject);
- 深拷贝的实现方式
let obj2 = JSON.parse(JSON.stringify(obj1))
- 会忽略 undefined
- 无法拷贝一些特殊的对象,诸如 RegExp, Date, Set, Map等
- 无法拷贝函数(划重点)。
- 会抛弃对象的constructor,所有的构造函数会指向Object
- 不能解决循环引用的对象
var newObject = $.extend(true, {}, oldObject);
- lodash deepClone
手写深拷贝
- 若属性为值类型,则直接返回;若属性为引用类型,则递归遍历。
function deepClone(obj) {
if(typeof obj !== 'object' || obj === null) {
return obj
}
let copy = {}
if(obj.constructor === Array) {
copy = []
}
for(let key in obj) {
if(obj.hasOwnProperty(key)) {
copy[key] = deepClone(obj[key])
}
}
return copy
}
- 解决循环引用:创建一个WeakMap。记录下已经拷贝过的对象,如果说已经拷贝过,那直接返回它行了。