深拷贝
前言
这个话题在面试上已经是老生常谈了,今天让我们一起来学习下深拷贝。
定义
在引出定义前,我们先来看下面的例子:
var arr = [{
name: 'foo'
}, {
age: 20
}]
var newArr = arr.concat()
newArr[0].name = 'bar'
newArr[1].age = 24
console.log(arr) // [{name: "bar"}, {age: 24}]
console.log(newArr) // [{name: "bar"}, {age: 24}]
分析:首先 concat()
方法拷贝了 arr 对象到 newArr,但是我们改变 newArr 数组对象的值时,arr 的数组对象也会随着变化。为了不影响原数组对象的值,我们就需要使用深拷贝。
因此,深拷贝指的是创建一个新的对象和数组,将原对象的各项属性的「值」(数组的所有元素)拷贝过来,是「值」而不是「引用」。
实现
在拷贝的时候判断一下属性值的类型,如果是对象,我们就递归调用深拷贝函数。见下方:
function cloneDeep (val) {
if (typeof val === 'object') {
var newVal = val instanceof Array ? [] : {}
for (var key in val) {
if (val.hasOwnProperty(key)) {
newVal[key] = typeof val[key] === 'object' ? cloneDeep(val[key]) : val[key]
}
}
return newVal
}
}
var arr = [{
name: 'foo'
}, {
age: 20
}]
var newArr = cloneDeep(arr)
newArr[0].name = 'bar'
newArr[1].age = 24
console.log(arr) // [{name: "foo"}, {age: 20}]
console.log(newArr) // [{name: "bar"}, {age: 24}]
性能问题
尽管使用深拷贝会完全的克隆一个新对象,不会产生副作用,但是深拷贝因为使用递归,性能会不如浅拷贝,在开发中,还是要根据实际情况进行选择。
结语
本文到这里就结束了。通过这篇文章了解深拷贝的定义和实现,以及它的性能问题。希望本文能够帮助到你,共勉!