# 深拷贝和浅拷贝
# 浅拷贝
实现浅拷贝的方法一般有2种, Object.assign
和 ...xx
操作符
const obj = {
name: 'chenying',
age: 18,
has: {
vue: true
}
}
const obj1 = {...obj}
obj1.name = 'ying'
console.log(obj) // { name: 'chenying', age: 18, has: { vue: true } }
console.log(obj1) // { name: 'ying', age: 18, has: { vue: true } }
const obj = {
name: 'chenying',
age: 18,
has: {
vue: true
}
}
const obj1 = Object.assign(obj)
obj1.name = 'ying'
console.log(obj) // { name: 'ying', age: 18, has: { vue: true } }
console.log(obj1) // { name: 'ying', age: 18, has: { vue: true } }
# 深拷贝
最简单的深拷贝方法是使用JSON.parse(JSON.stringify(obj))
const obj = {
name: 'chenying',
age: 18,
has: {
vue: true
}
}
const obj1 = JSON.parse(JSON.stringify(obj))
obj1.has.vue = false
console.log(obj) // { name: 'chenying', age: 18, has: { vue: true } }
console.log(obj1) // { name: 'chenying', age: 18, has: { vue: false } }
但是这个方法有点缺陷,例如
- 会忽略 undefined
- 会忽略 symbol
- 会忽略 正则 日期
- 不能序列化函数
- 不能解决循环引用的对象
所以一般我们会自己实现一个深拷贝函数
const obj = {
name: 'chenying',
age: 18,
has: {
vue: true
}
}
function deepcopy(value) {
if (value == null) { return value }
if (value instanceof RegExp) { return new RegExp(value) }
if (value instanceof Date) { return new Date(value) }
if (typeof value !== 'object') { return value }
let obj = new value.constructor() // 拿到[] 或者 {}
for (let key in value) {
obj[key] = deepcopy(value[key])
}
return obj
}
let obj1 = deepcopy(obj)
obj1.has.vue = false
console.log(obj) // { name: 'chenying', age: 18, has: { vue: true } }
console.log(obj1) //{ name: 'chenying', age: 18, has: { vue: false } }
但是这样写有一个缺陷,就是容易爆栈,例如我们这样调用
let obj2 = {}
obj2.x = obj2
let obj3 = deepcopy(obj2)
console.log(obj3)
那我们可以使用WeakMap
的特性判断,如果之前这个值已经拷贝过了,就不需要在进行拷贝了
function deepcopy(value, hash = new WeakMap) {
if (value == null) { return value }
if (value instanceof RegExp) { return new RegExp(value) }
if (value instanceof Date) { return new Date(value) }
if (typeof value !== 'object') { return value }
let obj = new value.constructor() // 拿到[] 或者 {}
if (hash.get(value)) { // 如果hash表里面有这个值就不需要走拷贝了
return hash.get(value)
}
hash.set(value, obj)
for (let key in value) {
obj[key] = deepcopy(value[key], hash)
}
return obj
}
← ES6食用指南 你不知道的require →