js中对象的深拷贝与浅拷贝

一、概念

1.1 浅拷贝

浅拷贝:只拷贝对象中的基本类型的数据,而引用类型数据,复制后也是会发生引用。
简单来说,浅拷贝只复制指向某个对象的指针,这个指针指向对象在内存中保存的地址,并不会复制对象本身,新旧对象共享同一块内存

示意图如图所示:
其中,0x2000代表对象在内存中的地址,obj1与obj2共同指向0x2000
在这里插入图片描述

1.2 深拷贝

深拷贝:将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上,并开辟了一块新的内存地址来存放复制的对象

示意图如图所示:
其中,0x2000代表旧对象在内存中的地址,0x3000代表复制出的新对象在内存的地址,obj1与obj2分别指向0x2000与0x3000
在这里插入图片描述

二、拷贝方式

2.1 直接赋值

2.1.1 基本数据类型的拷贝

// 
let obj1 = {
    name: 'zs',
    age: 18,
    gender: '男',
  }
  console.log(obj1)
  let obj2 = obj1
  obj2.name = 'ls'
  console.log(obj2)

输出结果:
在这里插入图片描述

根据结果可以得知:对于只有一层基本类型数据的对象而言,是深拷贝。

2.1.2 引用类型的拷贝

    // 新建obj1对象
    let obj1 = {
      name: 'zs',
      age: 18,
      gender: '男',
      score: {
        Math: 80,
        English: 90
      }
    }
    console.log(obj1)
    let obj2 = obj1
    obj2.score.Math = 85
    console.log(obj2)

输出结果:
在这里插入图片描述
根据输出结果可以得知:改动拷贝对象obj2.score.Math的值为85后,原对象obj1.score.Math的值也被改为了85。这也是浅拷贝

直接赋值的方式虽然简单,但是只能深拷贝第一层的基本类型数据,引用类型还是浅拷贝。

2.2 Object.assign()方法

在ES6中,关于对象的复制,则提出了Object.assign()方法,该方法只能实现浅复制

   let obj1 = {
      name: 'zs',
      age: 18,
      gender: '男',
      score: {
        Math: 80,
        English: 90
      }
    }
    console.log(obj1)
    let obj2 = {}
    Object.assign(obj2, obj1)
    obj2.score.Math = 85
    console.log(obj2)

输出结果
在这里插入图片描述

2.3 ES6中的扩展运算符(…)

   let obj1 = {
      name: 'zs',
      age: 18,
      gender: '男',
      score: {
        Math: 80,
        English: 90
      }
    }
    console.log(obj1)
    let obj2 = {...obj1}
    obj2.score.Math = 85
    obj2.name = 'ls'
    console.log(obj2)

输出结果:
在这里插入图片描述

根据输出结果可以看到obj1和obj2的各自的name属性被修改了,但是score.Math仍然共同一个数据,此为浅拷贝。

2.4 jQuery中的 $.extend

语法格式:$.extend(deep,target,object1,objectN)
参数含义:
deep: 设为true代表深拷贝,默认是false,即浅拷贝
target: 要拷贝的目标对象
object1: 待拷贝到第一个对象的对象
objectN: 待拷贝到第N个对象的对象

    let obj1 = {
      name: 'zs',
      age: 18,
      gender: '男',
      score: {
        Math: 80,
        English: 90
      }
    }
    console.log(obj1)
    let obj2 = {}
    $.extend(obj2, obj1) // 浅拷贝
    obj2.score.Math = 85
    console.log(obj2)

输出结果:
在这里插入图片描述

    let obj1 = {
      name: 'zs',
      age: 18,
      gender: '男',
      score: {
        Math: 80,
        English: 90
      }
    }
    console.log(obj1)
    let obj2 = {}
    $.extend(true, obj2, obj1) // 深拷贝
    obj2.score.Math = 85
    console.log(obj2)

输出结果:
在这里插入图片描述
利用前端框架JQuery的方法性能很高,使用起来也很容易,但每次要使用都需要导入这个库,算是一个美中不足的地方了。

2.5 递归方式

function deepCopy(oldObj, newobj) {
    for (var key in oldObj) {
      var item = oldObj[key];
      // 判断是否是对象
      if (item instanceof Object) {
        newobj[key] = {};  //定义一个空的对象来接收拷贝的内容
        deepCopy(item, newobj[key]); //递归调用
        // 判断是否是数组
      } else if (item instanceof Array) {
        newobj[key] = [];  //定义一个空的数组来接收拷贝的内容
        deepCopy(item, newobj[key]); //递归调用
      } else {
        newobj[key] = oldObj[key];
      }
    }
  }
  let obj1 = {
      name: 'zs',
      age: 18,
      gender: '男',
      score: {
        Math: 80,
        English: 90
      }
    }
    console.log(obj1);
    let obj2 = {}
    deepCopy(obj1, obj2)
    obj2.score.Math = 85
    console.log(obj2)

输出结果:
在这里插入图片描述
利用递归的方法完成对对象的深拷贝,虽然繁琐,代码也很长,但也是一种有效的方法。

2.6 JSON.parse(JSON.stringify())

原理:用JSON.stringify()将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,这是一个新的对象,而且对象会开辟新的栈,实现深拷贝。

    let obj1 = {
      name: 'zs',
      age: 18,
      gender: '男',
      score: {
        Math: 80,
        English: 90
      }
    }
    console.log(obj1);
    let obj2 = JSON.parse(JSON.stringify(obj1))
    obj2.score.Math = 85
    console.log(obj2)

输出结果:
在这里插入图片描述
注意: 这种方法尽管可以实现对对象的深拷贝,但是会忽略掉原对象中定义的方法

    let obj1 = {
      name: 'zs',
      age: 18,
      gender: '男',
      score: {
        Math: 80,
        English: 90
      }
    }
    console.log(obj1);
    let obj2 = JSON.parse(JSON.stringify(obj1))
    obj2.score.Math = 85
    console.log(obj2)

在这里插入图片描述
可以看到在obj2中没有fn这个方法,因为被忽略掉了。

三、学习总结

虽然拷贝对象的方式有很多,但是其拷贝的程度并不一致。在开发中,要根据业务需要,选择合适的方式来拷贝对象。

  1. 直接复制 实现的是浅拷贝,只拷贝对象的基本类型的数据
  2. 使用JS原生的递归方法是做复杂深拷贝的好方法,虽然代码繁琐,但兼顾了兼容性。
  3. 使用JSON的两种方法深拷贝只能是对象中没有函数时才能使用
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值