浅拷贝与深拷贝

1.明确深拷贝和浅拷贝的概念

  • 浅拷贝只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做浅拷贝。浅拷贝只是复制指向某个对象的指针(引用地址),而不复制对象本身,新旧对象还是共享同一块内存。

  • 深拷贝在堆中重新分配内存,并且把源对象所有属性都进行新建拷贝,以保证深拷贝的对象的引用图不包含任何原有对象或对象图上的任何对象,拷贝后的对象与原来的对象是完全隔离,互不影响。 

2. 浅拷贝方法

1. 直接赋值

直接赋值是常见的浅拷贝方式

 let p1 = {
    name: 'xiejie',
    age: 18
 }
 //  直接赋值
 let p2 = p1;

2. Object.assign 方法

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。语法 Object.assign(新对象,被拷贝对象)

let p1 = { name: '张三', age: 17, info: { score: 100 } }
let p2 = Object.assign({}, p1)
p2.info.score = 99
console.log(p1.info.score)  // 99 

3.for in 语法

将对象/数组的第一层数据复制一份给另一个空对象

 let p1 = { name: '张三', age: 17, info: { score: 100 } }
 let p2 = {}
 for (const k in p1) {
     // 只拷贝了一层
     p2[k] = p1[k]
     // 如果第一层数据是对象或数组 则仅仅拷贝地址
 }
 p2.info.score = 99
 console.log(p1.info.score) // 99

3.深拷贝方法

1. JSON.parse(JSON.stringify)

JSON.stringify()会忽略对象中的函数和undefined值以及无法转换的特殊数据类型 Date  RegExp Map Set

 let p1 = {
            name: '张三',
            age: 18,
            info: {
                score: 100,
                hobby: ['篮球', '足球','排球', [1, 2, 3]]
            },
            fn: function () {
                console.log('这是一个函数!')
            }
        }
        // 使用JSON方法实现深拷贝
          let str = JSON.stringify(p1)
          console.log(str)
          let p2 = JSON.parse(str)
          p2.name = '李四'
          p2.info.hobby[0] = '乒乓球'
          console.log(p2)
          console.log(p1)

打印p1,p2结果如下:p2丢失了 fn函数方法 和 undefined

JSON.stringify 方法是将一个 javascript 值(对象或者数组)转换为一个 JSON 字符串,而 JSON 字符串是不能够接受函数的。同样,JSON.stringify()会删除具有undefined值的属性,因为 JSON 规范不允许undefined值。

2.递归方法(推荐)

// 使用递归实现深拷贝
    function deepClone(target) {
      var result;
      // 判断是否是对象类型
      if (typeof target === 'object') {
        // 判断是否是数组类型
        if (Array.isArray(target)) {
          result = []; // 如果是数组,创建一个空数组
          // 遍历数组的键
          for (var i in target) {
            // 递归调用
            result.push(deepClone(target[i]))
          }
        } else if (target === null) {
          // 再判断是否是 null
          // 如果是,直接等于 null
          result = null;
        } else if (target.constructor === RegExp) {
          // 判断是否是正则对象
          // 如果是,直接赋值拷贝
          result = target;
        } else if (target.constructor === Date) {
          // 判断是否是日期对象
          // 如果是,直接赋值拷贝
          result = target;
        } else {
          // 则是对象
          // 创建一个空对象
          result = {};
          // 遍历该对象的每一个键
          for (var i in target) {
            // 递归调用
            result[i] = deepClone(target[i]);
          }
        }
      } else {
        // 表示不是对象类型,则是简单数据类型  直接赋值
        result = target;
      }
      // 返回结果
      return result;
    }

    let stu = {
      name: 'xiejie',
      age: 18,
      stuInfo: {
        No: 1,
        score: 100,
        saySth: function () {
          console.log('我是一个学生');
        }
      }
    }
    let stu2 = deepClone(stu)
    stu.age = 17
    console.log(stu) 
    console.log(stu2) //完成深拷贝

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在下逼王尘少

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值