目录
深浅拷贝
首先浅拷贝和深拷贝只针对引用类型
浅拷贝
拷贝的是地址
直接复制对象(数组)的问题:当被赋值的对象(数组)修改属性或者方法时,原对象(数组)中的属性或者方法也会被修改
<script>
const obj = {
uname: 'zs',
age: 18
}
const o = obj
o.age = 20
console.log(o) //{uname:'zs',age:20}
console.log(obj) //{uname:'zs',age:20}
</script>
常见方法:
- 拷贝对象:Object.assgin() / 展开运算符 {...obj} 拷贝对象
- 拷贝数组:Array.prototype.concat() 或者 [...arr]
<script>
const obj = {
uname: 'zs',
age: 18,
like: {
hobby: 'basketball'
}
}
// 浅拷贝
// const o = { ...obj }
// o.age = 20
// console.log(o) //{uname:'zs',age:20}
// console.log(obj) //{uname:'zs',age:18}
const o = {}
Object.assign(o, obj)
o.age = 20
o.like.hobby = 'baseball'
console.log(o) //{uname:'zs',age:20,like:{hobby:baseball}}
// 浅拷贝对简单数据类型在栈中直接将值修改,对引用数据类型是将地址赋给这个对象
// 这个对象和拷贝前的对象还是用同样的地址,在堆中指向同一个对象,两者都会被修改
console.log(obj) //{uname:'zs',age:18,like:{hobby:baseball}}
</script>
直接赋值和浅拷贝区分:
- 直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对 象栈里面的地址
- 浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会 相互影响
理解浅拷贝:拷贝对象之后,里面的属性值是简单数据类型直接拷贝值;如果属性值是引用数据类型则拷贝的是地址
深拷贝
拷贝的是对象,不是地址
常见方法:
- 通过递归实现深拷贝
- lodash/cloneDeep
- 通过JSON.stringify()实现
通过递归实现深拷贝
函数递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
-
简单理解:函数内部自己调用自己, 这个函数就是递归函数
-
递归函数的作用和循环效果类似
-
由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return
理解:深拷贝出来的对象对旧对象不会产生影响,利用函数递归实现深拷贝;当我们进行普通属性进行拷贝的时候直接赋值就行了,当遇到复杂数据类型比如数组的时候,再次调用递归函数就可以了,如果是对象形式,就利用递归解决对象问题。先Array再Object
<script>
const obj = {
uname: 'zs',
age: 18,
hobby: ['乒乓球', '足球'],
family: {
lover: 'ls'
}
}
const o = {}
// 拷贝函数
function deepCopy(newObj, oldObj) {
debugger
for (let k in oldObj) {
// 处理数组的问题 一定先写数组 在写 对象 不能颠倒
if (oldObj[k] instanceof Array) {
newObj[k] = []
// newObj[k] 接收 [] hobby
// oldObj[k] ['乒乓球', '足球']
deepCopy(newObj[k], oldObj[k])
} else if (oldObj[k] instanceof Object) {
newObj[k] = {}
deepCopy(newObj[k], oldObj[k])
}
else {
// k 属性名 uname age oldObj[k] 属性值 18
// newObj[k] === o.uname 给新对象添加属性
newObj[k] = oldObj[k]
}
}
}
deepCopy(o, obj) // 函数调用 两个参数 o 新对象 obj 旧对象
console.log(o)
o.age = 20
o.hobby[0] = '篮球'
o.family.lover = 'ww'
console.log(obj)
console.log([1, 23] instanceof Object)
</script>
lodash/cloneDeep
js库lodash里面cloneDeep内部实现了深拷贝
// 安装
$ npm i --sava lodash
<script>
const obj = {
uname: 'zs',
age: 18,
hobby: ['乒乓球', '足球'],
family: {
lover: 'ls'
}
}
const o = _.cloneDeep(obj)
console.log(o)
o.family.lover = 'ww'
console.log(obj)
</script>
通过JSON.stringify()实现
<script>
const obj = {
uname: 'zs',
age: 18,
hobby: ['乒乓球', '足球'],
family: {
lover: 'ls'
}
}
// 把对象转换为 JSON 字符串(就变成简单数据类型)
// console.log(JSON.stringify(obj))
const o = JSON.parse(JSON.stringify(obj))
console.log(o)
o.family.lover = 'ww'
console.log(obj)
</script>