• ES6 - 扩展运算符与Object.assign对象拷贝与合并


    扩展运算符能做什么?

    扩展运算符用来取出对象中所有可遍历属性,拷贝合并到当前对象中(当前对象是一个新的对象集合,和拷贝对象没有必然联系)也就是说这是一个浅拷贝,如果说它具体可以做什么的话,它可以拷贝一个或多个(合并)对象,拷贝一个数组或者多个(合并)数组


    什么是深浅拷贝

    对于深浅拷贝,大家第一印象就是深拷贝递归,浅拷贝循环

    其实对于深浅拷贝我在之前的博文中提到过了,在这里再多余阐述一下:

    let obj = {
      a: 10,
      b: 20,
      c: 30,
      d: 40,
      e: 66,
      f: 88,
    };
    
    // 深拷贝
    let obj2 = obj;
    
    // 修改obj2
    
    obj2.a = 100;
    
    console.log(obj.a, obj2.a);
    
    // 100 100
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    不难看出我只是修改了拷贝出来的对象,结果原对象的属性也被我修改了,我们不想这样

    这就需要我们探究它是怎么拷贝的,对于引用类型数据来说,拷贝出来的是一个真正的副本,再内存堆栈中它们的地址指向还是同一个,这就导致我们修改obj2的属性之后,修改的其实是对应地址中的数据,因为obj也指向那个地址,这就导致了俩个对象中的属性都被修改了,因为它们指向的是同一个地址呀

    那我们的思路是什么?不就是新开创一个地址嘛,再给obj2开创一个新的地址不就可以了吗?

    let obj = {
      a: 10,
      b: 20,
      c: 30,
      d: 40,
      e: 66,
      f: 88,
    };
    
    // 给到 obj2 一个新的内存地址
    let obj2 = {};
    
    for (const key in obj) {
      obj2[key] = obj[key];
    }
    
    obj2.b = 200;
    
    console.log(obj.b, obj2.b);
    
    // 20 200
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    解决了,这运用到了浅拷贝的原理


    使用ES6扩展运算符

    对象浅拷贝

    还是上面的例子,我们使用扩展运算符来实现一个浅拷贝

    let obj = {
      a: 10,
      b: 20,
      c: 30,
      d: 40,
      e: 66,
      f: 88,
    };
    
    let obj2 = { ...obj };
    
    obj2.b = 200;
    
    console.log(obj.b, obj2.b);
    
    // 20 200
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    如果你是第一次使用扩展运算符,那么你一定会感叹真的是:好用的妈妈给好用开门 - 好用到家了

    对象合并

    let obj = {
      a: 10,
      b: 20,
      c: 30,
    };
    
    let obj2 = {
      d: 40,
      e: 66,
      f: 88,
    };
    
    let obj3 = { ...obj, ...obj2 };
    
    console.log(obj3);
    
    // { a: 10, b: 20, c: 30, d: 40, e: 66, f: 88 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    数组也是类似,我就不做过多阐述了


    Object.assign

    Object.assign不同于扩展运算符的是:它针对于对象的处理与执行,同样是浅拷贝却比扩展运算符的性能高,常常用来给对象添加属性以及方法

    Object.assign详解

    准确来说它用于将所有可枚举属性的值从一个或者多个原对象浅拷贝到目标对象,返回值为目标对象
    (如果目标对象中的属性具有相同的键,那么这些冲突属性将会被原对象对应属性所覆盖,如果是多个原对象合并,那么后面的原对象将依次覆盖)

    Object.assign( 目标对象 , 原对象1 ,原对象2 ...)

    let obj = {
      a: 10,
      b: 20,
      c: 30,
    };
    
    let obj2 = {
      a: 40,
      e: 66,
      c: 88,
    };
    
    let obj3 = {};
    
    let new_obj = Object.assign(obj3, obj, obj2);
    
    console.log(Object.assign(obj3, obj, obj2));
    
    console.log(new_obj);
    
    // { a: 40, b: 20, c: 88, e: 66 }
    // { a: 40, b: 20, c: 88, e: 66 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    重复覆盖,非重复合并

    • 如果只有一个目标对象,则返回该对象
    • 如果目标对象不是一个对象,JavaScript 会在后台帮我们转成一个对象
    // 基于自动转对象这个我们写一个例子
    const stringToObject = Object.assign('Hello_World');
    
    console.log(stringToObject);
    console.log(stringToObject[0]);
    
    // [String: 'Hello_World']
    // H
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    请添加图片描述

    • 目标对象不能是 undefined 或者 null,会报错

    Object.assign()实用

    给对象添加属性

    function Test(name, age, hobby) {
      Object.assign(this, { name, age, hobby });
    }
    const test = new Test('Brave-AirPig', 22, '跑步');
    
    console.log(test);
    
    // Test { name: 'Brave-AirPig', age: 22, hobby: '跑步' }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    class Test {
      constructor(name, age, hobby) {
        Object.assign(this, { name, age, hobby });
      }
    }
    
    const test = new Test('名字', '22', '打代码');
    
    console.log(test);
    
    // Test { name: '名字', age: '22', hobby: '打代码' }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    给对象添加方法

    class Test {
      constructor(name, age, hobby) {
        Object.assign(this, { name, age, hobby });
      }
    }
    
    const test = new Test('名字', '22', '打代码');
    
    Object.assign(Test.prototype, {
      run() {
        console.log('跑起来');
      },
    });
    
    test.run();
    // 跑起来
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    function Test(name, age, hobby) {
      Object.assign(this, { name, age, hobby });
    }
    const test = new Test('Brave-AirPig', 22, '跑步');
    
    Object.assign(Test.prototype, {
      run() {
        console.log('跑起来');
      },
    });
    
    test.run();
    // 跑起来
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    如果我们使用ES5的话可以这样写:

    class Test {
      constructor(name, age, hobby) {
        Object.assign(this, { name, age, hobby });
      }
    }
    
    const test = new Test('名字', '22', '打代码');
    
    Test.prototype.run = () => console.log('跑起来');
    
    test.run();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    就是直接往原型上添加方法呗 🤔

  • 相关阅读:
    如何将网站部署到浏览器?
    自由职业者是一个趋势吗?
    图片像素缩放,支持个性化自定义与精准比例调整,让图像处理更轻松便捷!
    2022牛客多校第四场C.Easy Counting Problem
    MybatisPlus整合SpringBoot
    速盾:dns和cdn区别?
    为什么这么多人都想当产品经理?
    P1843 奶牛晒衣服 【贪心】
    DataTable扩展 列转行方法(2*2矩阵转换)
    DJ 12-3 程序控制指令
  • 原文地址:https://blog.csdn.net/weixin_63836026/article/details/126284858