深浅拷贝
-
首先浅拷贝和深拷贝只针对想Object,Array这样的复杂对象,简单来说,浅拷贝只复制一层对象的属性,二深拷贝则复制了所有的层级。
-
对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没 有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会 改变,而深复制则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
浅拷贝
//1. 浅拷贝就是对象或数组中的值 不能拷贝复杂数据类型
// 都是简单数据类型,就是个改个的 复杂数据类型改一个另一个也改变
const obj1 = {}
const obj2 = { name: '宇智波带土', age: 18, friends: ['琳'] }
Object.assign(obj1, obj2) // obj2 的值 给obj1
console.log(obj1)
console.log(obj2)
//修改对象中的简单数据类型 另一个不会发生改变
obj1.name = '宇智波鼬'
obj1.friends.push('班主任')
console.log(obj1)
console.log(obj2)
// 拓展 数组里的浅拷贝
const arr1 = [1, 2, 3].concat()
console.log(arr1)
const arr2 = [...arr1]
console.log(arr2)
修改对象中的简单数据类型的值 另一个不会发生改变
修改复杂数据类型中的值 另一个也会跟着改变
所以这个时候就需要用到深拷贝
深拷贝
1.利用JSON深拷贝
// 利用json中的方法,把一个对象转换成字符串 然后再将他解析成对象
const obj1 = {name:'宇智波带土',age:18,friends:['旗木卡卡西']}
// 利用JSON深拷贝
const obj2 = JSON.parse(JSON.stringify(obj1))
//修改一个值 另一个值不会改变
obj1.name = '宇智波佐助'
obj1.age = 25
obj1.friends.push('火影鸣人')
console.log(obj1)
console.log(obj2)
2.利用lodash中的_.cloneDeep进行深拷贝
<!-- 引入lodash.min.js -->
<script src="./lodash.min.js"></script>
<script>
//1.JSON.stringify()不识别函数
const obj1 = {name:'宇智波带土',age:18,friends:['旗木卡卡西'],fn:()=> console.log(123)}
console.log(JSON.stringify(obj1)) //得不到方法 不会解析函数
// 想要识别函数 , 进行深层赋值 必须引入lodash.min.js
// consol.log('_'); //引入lodash.min.js 就能够使用_ 这个变量
const obj2 = _.cloneDeep(obj1)
console.log(obj1)
console.log(obj2)
obj1.name = '六道佩恩'
obj1.friends.push = '小南'
console.log(obj1)
console.log(obj2)
3.利用递归进行深拷贝
// 1. 递归就是函数自己调用自己
// 递归要有停止条件,否则就是死递归
// 条件1 调出有条件
// 条件2 跳出有条件
//计数器
let count = 0
// 条件1 . 调用有条件 重要的事情说三遍
function fn1() {
console.log('重要的事情说三遍')
count++
if (count < 3) {
fn1() // 递归调用 满足条件就调用
}
}
// fn1()
//条件2 跳出有条件 重要的事情说三遍
function fn2() {
if (count >= 3) {
return
}
console.log('重要的事情说三遍')
count++
fn2()
}
fn2()
封装递归方法
<script>
// 定理: 所有复杂数据类型 分析到最后 一定会是两种数据类型:函数 和 简单数据类型
// 封装一个方法,实现深层复制 把obj2里面的各种属性值 复制到obj1里面去
function cloneDeep(obj1, obj2) {
for (let k in obj2) {
//判断属性值的类型 Array Object 其他类型就可以当作简单类型操作
// A instanceof B 的意思就是 A是否是B创建的
//因为所有对象都是Object创建的 所以判断数组应该再判断对象之前
if (obj2[k] instanceof Array) {
obj1[k] = [] //设置OBJ1里面的相同属性为一个空数组
cloneDeep(obj1[k], obj2[k]) //递归通过数组赋值
} else if (obj2[k] instanceof Object) {
obj1[k] = {} //设置OBJ1里面的相同属性为一个空对象
cloneDeep(obj1[k], obj2[k]) //递归通过数组赋值
} else {
//如果只考虑浅拷贝 那么就可以使用for... in... 遍历obj2 然后让obj1里面也赋值一份
obj1[k] = obj2[k];
}
}
}
const o1 = { name: '宇智波佐助', age: 18, friends: '旗木卡卡西', aaa: { a: 1, b: 2 } }
const o2 = {}
cloneDeep(o2, o1)
console.log(o1)
console.log(o2)
//修改o1里面的属性
o1.name = '宇智波带土'
o1.age = 25
o1.friends.push = '鸣人'
console.log(o1)
console.log(o2)