深拷贝&浅拷贝

文章介绍了JavaScript中浅拷贝的概念,包括直接赋值、Object.assign和展开运算符的使用,并指出它们在处理多层对象时的问题。接着讨论了深拷贝的必要性,提到了通过JSON序列化、lodash库的_.cloneDeep方法以及自定义递归函数实现深拷贝的方法,同时指出了这些方法的局限性和适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

浅拷贝

浅拷贝:把对象拷贝给一个新的对象,开发中我们经常需要复制一个对象

如果直接赋值,则复制的是地址,修改任何一个对象,另一个对象都会变化
浅拷贝:

  • 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)

        // 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.如果属性值是基本数据类型,直接赋值即可
        */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值