直接赋值、浅拷贝、深拷贝的区别以及深拷贝的几种写法

深拷贝、浅拷贝以及直接赋值,到底有啥区别呢?在什么时候我应该用哪一种呢?在一段代码中,我们通常就是拿来直接赋值,直接用。似乎涉及到拷贝的情况没那么多,但是如果对值有操作但是又想保留原先的值,那就不能用直接赋值,需要使用到拷贝。

直接赋值

直接赋值,应该是代码中常见的。但是如果需要对结果进行操作的话,那么不管对象的属性是基本类型还是引用类型都会被修改

let testObj = {
  name : 'test',
  arr : [1,2,3,4],
  test: function (){
     console.log('可以复制出来吗?')
  }
}
let newObj = testObj
newObj.name = 'newTest'
console.log('testObj',testObj)
console.log('newObj',newObj)

![在这里插入图片描述](https://img-blog.csdnimg.cn/bc24b5b144074b6b8b1102c699eb0950.png

浅拷贝

浅拷贝会比直接赋值好一点,被浅拷贝后,如果是基础类型发生改变,是不会被影响的,但是引用类型还是会被修改。

let testObj = {
  name : 'test',
  arr : [1,2,3,4],
  obj : { nameObj : '测试' }test : function (){
     console.log('可以复制出来吗?')
  }
}
let newObj = {...testObj}
newObj.name = 'newTest'
newObj.arr[1] = 5
newObj.obj.nameObj = '修改'
console.log('testObj',testObj)
console.log('newObj',newObj)

![在这里插入图片描述](https://img-blog.csdnimg.cn/967306ecb6994170b821866336a90607.png

深拷贝

深拷贝无论是基础类型发生改变,还是引用类型被改变,都不会被修改。下面先用简单的方法实现:

let testObj = {
  name : 'test',
  age: NaN,
  time: new Date(),
  arr : [1,2,3,4],
  obj : { nameObj : '测试' },
  test : function (){
     console.log('可以复制出来吗?')
  }
}
let newObj = JSON.parse(JSON.stringify(testObj))
newObj.name = 'newTest'
newObj.obj.nameObj = '修改'
console.log('testObj',testObj)
console.log('newObj',newObj)

![在这里插入图片描述](https://img-blog.csdnimg.cn/25429dbd4bd34f6b8a649170d0676214.png

基础类型和引用类型没有发生改变,但是JSON.stringify对js对象序列化,再通过JSON.parse反序列化还原,会导致函数丢失、时间以字符串的方式展示、对象中的正则表达式也会为空(如图)。所以在使用JSON.stringify和JSON.parse进行深拷贝时要格外注意。下面就对这个简洁版的深拷贝,来个功能完善的基础版。

function deepCopy(obj){
  let copy = {}
  for(let key in obj) {
    if(obj.hasOwnProperty(key)){
      copy[key] = obj[key]
    }
  }
  return copy
}
let testObj = {
  name : 'test',
  age: NaN,
  time: new Date(),
  arr : [1,2,3,4],
  obj : { nameObj : '测试' },
  test : function (){
     console.log('可以复制出来吗?')
  }
}
let newObj = deepCopy(testObj)
newObj.name = 'newTest'
newObj.obj.nameObj = '修改'
console.log('testObj',testObj)
console.log('newObj',newObj)

在这里插入图片描述
但上面的写法,也有问题,当对象中有对象时,就还是会被修改,下面用递归来实现。

function deepCopy(obj){
// 在这一步可以加一个判断,判断obj是数组还是object
 // let copy = {}
 let copy = Array.isArray(obj)? []:{}
 // 判断一下obj是否为空,类型
 if(obj && typeof obj === 'object') {
   for(let key in obj) {
    if(obj.hasOwnProperty(key)){
      if(obj[key] && typeof obj[key]  === 'object'){
      // 判断是不是为日期
        if(obj[key] instanceof Date){
           // 这两种写法都可以
          // copy[key] = obj [key]
          copy[key] = new Date(obj [key].valueOf())
        } else {
          copy[key] = deepCopy(obj[key])
        }
      } else {
        copy[key] = obj[key]
      }
      } else {
        copy[key] = obj[key]
      }
    }
  }
 }
  return copy
}
let testObj = {
  name : 'test',
  age: NaN,
  time: new Date(),
  arr : [1,2,3,4],
  obj : { nameObj : '测试' },
  test : function (){
     console.log('可以复制出来吗?')
  }
}
let newObj = deepCopy(testObj)
newObj.name = 'newTest'
newObj.arr[1] = 5
newObj.obj.nameObj = '修改'
console.log('testObj',testObj)
console.log('newObj',newObj)

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值