浅拷贝
浅拷贝:把对象拷贝给一个新的对象,开发中我们经常需要复制一个对象
如果直接赋值,则复制的是地址,修改任何一个对象,另一个对象都会变化
浅拷贝:
- Object.assign()
- 展开运算符 […arr]
注意:
-
如果是基本类型拷贝值
-
如果是引用类型拷贝的是地址
如果是单层对象,没问题,如果有多层就有问题,会影响原来对象
// 把对象拷贝给一个新的对象,开发中我们经常需要复制一个对象
// 直接赋值---两个对象使用同一个地址 修改会相互影响
const obj = {
name: "佩奇"
}
const newObj = obj
newObj.name = '乔治'
console.log(obj.name) //'乔治'
// 常见方法
// 拷贝对象 Object.assign {...obj}
const obj = {
name: "佩奇"
}
// const newObj ={}
// Object.assign(newObj,obj)
// console.log(newObj===obj) //false
// newObj.name="乔治"
// console.log(newObj)
// console.log(obj)
// ------------
// const newObj={...obj}
// console.log(newObj===obj) //false
// newObj.name="乔治"
// console.log(newObj)
// console.log(obj)
// 拷贝数组 Array.prototype.concat() [...arr]
const arr = ['佩奇', '乔治']
// const arr1 = []
// const newArr = arr1.concat(arr)
// console.log(newArr)
// newArr[1] ="pig"
// console.log(arr)
// console.log(newArr)
// const newArr = [...arr]
// console.log(newArr)
// newArr[1] ="pig"
// console.log(arr)
// console.log(newArr)
// 浅拷贝的问题---遇到多层拷贝会影响原来的数组
const obj1 = {
name: "佩奇",
family: {
father: "pig爸爸"
}
}
const newObj = { ...obj1 }
newObj.family.father = 'dad'
console.log(newObj)
console.log(obj1)
深拷贝
深拷贝:拷贝多层,不再拷贝地址
方法:
- 通过JSON序列化实现
问题:不会转化undefined和function
// 通过JSON序列化实现(常用)
// JSON.stringify() 序列号为JSON字符串,再JSON.parse() 转为对象格式
const obj={
name:"佩奇",
family:{
father:"pig爸爸"
},
hobby:['唱歌','跳舞']
}
// console.log(JSON.stringify(obj))
const newObj =JSON.parse(JSON.stringify(obj))
console.log(newObj ===obj) //false
newObj.family.father = 'dad'
console.log(obj)
console.log(newObj)
注意 JSON.stringfy序列化的时候会忽略 function undefined
const obj={
name:"佩奇",
love:undefined,
family:{
father:"pig爸爸"
},
hobby:['唱歌','跳舞'],
sayHi(){
console.log("我会唱歌")
}
}
const newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)
- lodash库实现 https://www.lodashjs.com/
1.引入lodash库
2.使用_.cloneDeep
// js库lodash里面 _.cloneDeep 内部实现了深拷贝
const obj={
name:"佩奇",
love:undefined,
family:{
father:"pig爸爸"
},
hobby:['唱歌','跳舞'],
sayHi(){
console.log("我会唱歌")
}
}
const newObj =_.cloneDeep(obj)
newObj.family.father ='dad'
console.log(obj)
console.log(newObj)
- 通过递归实现
// 先判断拷贝的是数组还是对象{} []
const obj = {
name: "佩奇",
family: {
baby: "小佩奇"
},
hobby: ["唱歌", '跳舞']
}
// 封装深拷贝函数 cloneDeep
function cloneDeep(oldObj) {
// 1.先判断拷贝的是数组还是对象
const newObj = Array.isArray(oldObj) ? [] : {}
// 遍历拷贝属性和值
for (let k in oldObj) {
// console.log(k,oldObj[k]) //k 是属性 oldObj[k] 值
// 把旧对象的值给新对象的属性
if (typeof oldObj[k] === 'object') {
// 如果属性是引用数据类型,则需要递归再次拷贝
newObj[k] = cloneDeep(oldObj[k])
} else {
// 属性是基本数据类型,则直接赋值即可
newObj[k] = oldObj[k]
}
}
// 返回新对象
return newObj
}
const newObj = cloneDeep(obj)
console.log(newObj)
newObj.family.father = 'dad'
console.log(newObj)
console.log(obj)
/*
思路:
1.深拷贝的核心是利用函数递归
2.封装函数,里面先判断拷贝的是数组还是对象
3.开始遍历
4.如果属性值是引用数据类型(数组/对象) 则再次递归函数
5.如果属性值是基本数据类型,直接赋值即可
*/