深拷贝和浅拷贝的区别

1、浅拷贝

定义: 把对象拷贝给一个新对象,开发中我们经常需要复制一个对象。可以直接拷贝一个新的对象,如果直接赋值,则复制的是地址,修改任何一个对象,另一个对象都会改变。

常见方法:

1、拷贝对象:

Object.assign()

展开运算符{...obj

 2、拷贝数组:

Array.prototype.concat()

展开运算符 [...arr

代码如下: 

const Obj = {
            name: '张三'
        }
        // Object.assign({},对象) 对象拷贝的方法
        const newObj = Object.assign({},Obj)
        // 展开运算符的拷贝方法
        // const newObj = {...Obj}
        newObj.name = '李四'
        console.log(Obj)
        console.log(newObj)

        const arr = ['张三']
        // [].concat(数组) 数组拷贝的方法
        // const newArr = [].concat(arr)
        // 展开运算符的拷贝方法
        const newArr = [...arr]
        newArr[0] = '李四'
        console.log(arr)
        console.log(newArr)

 总结:对象和数组的浅拷贝就是把对象里面的属性和值复制一份,放到新对象中存储,新老对象是不同的地址值,所以修改其中一个对象,不会影响另一个对象的属性。

浅拷贝注意点:

1、如果是基本数据类型拷贝值

2、如果是引用数据类型拷贝的是地址

简单理解:如果是单侧对象,没有问题,如果有多层就有问题,还是会影响原来对象,浅拷贝就是只开被对象第一层的数据,如果对象都是基本数据类型则没有任何问题,只要有引用数据类型的属性,就会将其地址值复制一份,导致两个对象的属性共用同一个对象。

2、深拷贝

深拷贝:拷贝多层,不再拷贝地址

常见方法:

1、通过 JSON 序列化实现 

利用 JSON 的序列化和反序列化机制,取巧的方案,非常简单好用。

序列化:将对象转成字符串 JSON.stringify()

反序列化:将字符串转成对象 JSON.parse(

演示代码:

 const obj = {
            name: '张三',
            hoppy: ['吃饭','睡觉'],
            family: {
                father: '张四'
            }
        }
        // 利用 JSON 的序列化和反序列化机制
        // 1. 将对象转换为字符串
        const str = JSON.stringify(obj)
        // 2. 将字符串再转换为一个新的对象
        const OBJ = JSON.parse(str)
        // 这样就能实现深拷贝,对新对象进行修改不会影响旧对象

注意事项 使用 JSON.stringify() 和 JSON.parse() 进行深拷贝,无法拷贝 undefined 和 function。

2、lodash库 实现

js库 lodash里面 _.cloneDeep 内部实现了深拷贝

官网地址:Lodash 简介 | Lodash 中文文档 | Lodash 中文网

参数:需要深拷贝的对象

返回值:拷贝好的新对象

连同 undefined 和 function 和函数一并拷贝进来

对比第一种方法的优缺点:

优点:相较于序列化和反序列化的优势是更完善

缺点:需要额外引用一个第三方的 js 文件,增加项目体积

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./lodash.min.js"></script>
</head>
<body>
    <script>
        const obj = {
            name: '张三',
            hoppy: ['吃饭','睡觉'],
            family: {
                father: '张四'
            }
            age: undefined,
            gender:function(){}
        }
        // 这样就可以对newObj进行修改和获取函数和undefined的内容了 
         const newObj = _.cloneDeep(obj)
         newObj.name = '李四'
         console.log(obj)
         console.log(newObj)
    </script>
</body>
</html>

3、通过递归实现

定义:所谓递归就是一种函数调用自身的操作

1、简单理解:函数内部自己调用自己, 就是递归,这个函数就是递归函数

2、递归函数的作用和循环效果类似

3、由于递归很容易发生“栈溢出”错误(stack overflow),所以记得添加退出条件 return

实现代码:

 var obj= {
        "name":"张三",
        "age":22,
        "job":"程序员",
        "height":175,
        "type":{
            "character":"tender"
        }
    }
        obj.__proto__.say=function(){ 	}
    function deepCopy(obj){
	    var copyObj={ };
	    for(var key in obj){
		    if(obj.hasOwnProperty(key) == true){
				if(obj[key] instanceof Object){
						copyObj[key] = deepCopy(obj[key])
				}else{
							copyObj[key] = obj[key]
				}
		}
	}
	return copyObj;
}

var   obj2 = deepCopy(obj)
console.log(obj2)

实现思路:首先创建一个新对象,循环赋值,如果对象的属性值是对象,创建新对象,循环赋值。

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值