# 深浅拷贝
浅拷贝和深拷贝都是对于 JS 中的引用类型而言的,浅拷贝就只是复制对象的引用,如果拷贝后的对象发生变化,原对象也会发生变化。只有深拷贝才是真正地对对象的拷贝。
- 基本类型 Number,String,Boolean,Null,Undefined ,Symbol
- 引用类型 Object 类型、Array 类型、Date 类型、RegExp 类型、Function 类型 等
# 浅拷贝
只会将对象的各个属性进行依次复制,并不会进行递归复制,也就是说只会赋值目标对象的第一层属性
# 实现方式
- Array.concat()
- Object.assign()
- arr.slice()
- [...array]
- 函数库 lodash 的
_.clone
方法
# 深拷贝
# 实现方式
# 一 、JSON.parse()和 JSON.stringify()
缺点
- undefined、任意的函数、正则表达式类型以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)
- 它会抛弃对象的 constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成 Object
- 如果对象中存在循环引用的情况无法正确处理
# 二、函数库 lodash 的_.cloneDeep
方法
lodash.cloneDeep 源码 (opens new window)
# 三、jQuery.extend()方法
# 四、手写递归函数
var deepCopy = function (obj, map = new WeakMap()) {
// 基本类型
if (typeof obj !== 'object') {
return obj
}
// 数组和对象的处理
const newObj = obj instanceof Array ? [] : {}
// 循环引用的问题
if (map.has(obj)) {
return map.get(obj)
}
map.set(obj, newObj)
for (let key in obj) {
newObj[key] = deepCopy(obj[key], map)
}
return newObj
}
const a = { a: 1, b: [1, 2, 3], c: { a: { c: 1 } } }
const b = deepCopy(a)
a.c === b.c
// 循环引用测试用例
const target = {
field1: 1,
field2: undefined,
field3: {
child: 'child',
},
field4: [2, 4, 8],
}
target.target = target
const d = deepCopy(target)