• 03【解构赋值】


    解构赋值

    1.数组的解构赋值

    1.1 原理

    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

    以前,为变量赋值,只能直接指定值。

    let a = 1;
    let b = 2;
    let c = 3;
    
    • 1
    • 2
    • 3

    ES6 允许写成下面这样。

    let [a, b, c] = [1, 2, 3];
    
    • 1

    上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。

    1. 模式(结构)匹配 [] = [1, 2, 3];

    2. 索引值相同的完成赋值 const [a, b, c] = [1, 2, 3];

    3. 举例

      const [a, [, , b], c] = [1, [2, 3, 4], 5];
      console.log(a, b, c);	// 1 4 5
      
      • 1
      • 2

    1.2 数组解构赋值的默认值

    (1)默认值的基本用法

    const [a, b] = [];
    console.log(a, b);	// undefined undefined
    
    // ---------------------------------------
    const [a = 1, b = 2] = [];
    console.log(a, b);	// 1 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (2)默认值的生效条件

    只有当一个数组成员严格等于 (===) undefined 时,对应的默认值才会生效。

    const [a = 1, b = 2] = [3, 0];		// 3 0
    const [a = 1, b = 2] = [3, null];	// 3 null
    const [a = 1, b = 2] = [3];		    // 3 2
    
    • 1
    • 2
    • 3

    (3)默认值表达式

    如果默认值是表达式,默认值表达式是惰性求值的(即:当无需用到默认值时,表达式是不会求值的)

    const func = () => {
        return 24;
    };
    
    const [a = func()] = [1];	// 1
    const [b = func()] = [];	// 24
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1.3 数组解构赋值的应用

    (1)arguments

    function func() {
        const [a, b] = arguments;
        console.log(a, b);	// 1 2
    }
    func(1, 2);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (2)NodeList

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>NodeListtitle>
    head>
    <body>
    <p>1p>
    <p>2p>
    <p>3p>
    <script>
        const [p1, p2, p3] = document.querySelectorAll('p');
        console.log(p1, p2, p3);
        /*
        

    1

    2

    3

    */
    script> body> html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    (3)函数参数的解构赋值

    const array = [1, 1];
    // const add = arr => arr[0] + arr[1];
    const add = ([x = 0, y = 0]) => x + y;
    console.log(add(array));	// 2
    console.log(add([]));		// 0
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (4)交换变量的值

    let x = 2, y = 1;
    
    // 原来
    let tmp = x;
    x = y;
    y = tmp;
    
    // 现在
    [x, y] = [y, x];
    // 理解:[x, y] = [2, 1]
    console.log(x, y);
    // 1 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    (5)跳过某项值使用逗号隔开

    在解构数组时,可以忽略不需要解构的值,可以使用逗号对解构的数组进行忽略操作,这样就不需要声明更多的变量去存值了:

    var [a, , , b] = [10, 20, 30, 40];
    console.log(a);   // 10
    console.log(b);   // 40
    
    • 1
    • 2
    • 3

    上面的例子中,在 a、b 中间用逗号隔开了两个值,这里怎么判断间隔几个值呢,可以看出逗号之间组成了多少间隔,就是间隔了多少个值。如果取值很少的情况下可以使用下标索引的方式来获取值。

    (6)剩余参数中的使用

    通常情况下,需要把剩余的数组项作为一个单独的数组,这个时候我们可以借助展开语法把剩下的数组中的值,作为一个单独的数组,如下:

    var [a, b, ...rest] = [10, 20, 30, 40, 50];
    console.log(a);     // 10
    console.log(b);     // 20
    console.log(rest);  // [30, 40, 50]
    
    • 1
    • 2
    • 3
    • 4

    在 rest 的后面不能有 逗号 不然会报错,程序会认出你后面还有值。...rest 是剩余参数的解构,所以只能放在数组的最后,在它之后不能再有变量,否则则会报错。

    1.4 必须要分号的两种情况

    // 1. 立即执行函数
    // ;(function () { })();
    // (function () { })();
    
    // 2. 使用数组解构的时候
    // const arr = [1, 2, 3]
    const str = 'pink';
    [1, 2, 3].map(function (item) {
      console.log(item)
    })
    
    let a = 1
    let b = 2
      ;[b, a] = [a, b]
    
    console.log(a, b)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.对象的解构赋值

    2.1 原理

    对象的解构和数组基本类似,对象解构的变量是在 {} 中定义的。对象没有索引,但对象有更明确的键,通过键可以很方便地去对象中取值。在 ES6 之前直接使用键取值已经很方便了:

    var obj = { name: 'imooc', age: 7 };
    var name = obj.name;  // imooc
    var age = obj.age;    // 7
    
    • 1
    • 2
    • 3

    但是在 ES6 中通过解构的方式,更加简洁地对取值做了简化,不需要通过点操作增加额外的取值操作。

    var obj = { name: 'imooc', age: 7 };
    var { name, age } = obj;  // name: imooc, age: 7
    
    • 1
    • 2

    {} 直接声明 name 和 age 用逗号隔开即可得到目标对象上的值,完成声明赋值操作。

    1. 模式(结构)匹配 {} = {};
    2. 属性名相同的完成赋值 const {name, age} = {name: 'jerry', age: 18};const {age, name} = {name: 'jerry', age: 18};

    2.2 对象解构赋值的默认值

    1. 对象的属性值严格等于 undefined 时,对应的默认值才会生效。

    2. 如果默认值是表达式,默认值表达式是惰性求值的。

    对象的默认值和数组的默认值一样,只能通过严格相等运算符(===)来进行判断,只有当一个对象的属性值严格等于 undefined,默认值才会生效。

    var {a = 10, b = 5} = {a: 3};                 // a = 3, b = 5
    var {a = 10, b = 5} = {a: 3, b: undefined};   // a = 3, b = 5
    var {a = 10, b = 5} = {a: 3, b: null};        // a = 3, b = null
    
    • 1
    • 2
    • 3

    所以这里的第二项 b 的值是默认值,第三项的 null === undefined 的值为 false,所以 b 的值为 null。

    2.3 重命名属性

    在对象解构出来的变量不是我们想要的变量命名,这时我们需要对它进行重命名。

    var {a:x = 8, b:y = 3} = {a: 2};
    
    console.log(x); // 2
    console.log(y); // 3
    
    • 1
    • 2
    • 3
    • 4

    这里把 a 和 b 的变量名重新命名为 x 和 y。

    2.4 对象解构赋值的应用

    (1)对象作为函数参数

    // 之前
    const logPersonInfo = user => console.log(user.name, user.age);
    logPersonInfo({name: 'jerry', age: 18});
    
    // 之后
    const logPersonInfo = ({age = 21, name = 'ZJR'}) => console.log(name, age);
    logPersonInfo({name: 'jerry', age: 18});	// jerry 18
    logPersonInfo({});	// ZJR 21
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (2)复杂的嵌套(主要是缕清逻辑关系即可)

    const obj = {
        x: 1,
        y: [2, 3, 4],
        z: {
            a: 5,
            b: 6
        }
    };
    
    // ----------------------------------------------------
    const {x, y, z} = obj;
    console.log(x, y, z);	// 1 [ 2, 3, 4 ] { a: 5, b: 6 }
    
    // ----------------------------------------------------
    const {y: [, y2]} = obj;
    console.log(y2);	// 3
    console.log(y);		// 报错
    
    // ----------------------------------------------------
    const {y: y, y: [, y2]} = obj;
    console.log(y2);	// 3
    console.log(y);		// [ 2, 3, 4 ]
    
    // ----------------------------------------------------
    const {y, y: [, y2], z, z: {b}} = obj;
    console.log(y2);	// 3
    console.log(y);		// [ 2, 3, 4 ]
    console.log(z);		// { a: 5, b: 6 }
    console.log(b);		// 6
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    (3)剩余参数中的使用

    在对象的解构中也可以使用剩余参数,对对象中没有解构的剩余属性做聚合操作,生成一个新的对象。

    var {a, c, ...rest} = {a: 1, b: 2, c: 3, d: 4}
    console.log(a);     // 1
    console.log(c);     // 3
    console.log(rest);  // { b: 2, d: 4 }
    
    • 1
    • 2
    • 3
    • 4

    对象中的 b、d 没有被解构,通过剩余参数语法把没有解构的对象属性聚合到一起形成新的对象。

    2.5 注意点

    (1)如果要将一个已经声明的变量用于解构赋值,必须非常小心。

    // 错误的写法
    let x;
    {x} = {x: 1};
    // SyntaxError: syntax error
    
    • 1
    • 2
    • 3
    • 4

    上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。

    // 正确的写法
    let x;
    ({x} = {x: 1});
    
    • 1
    • 2
    • 3

    上面代码将整个解构赋值语句,放在一个圆括号里面,就可以正确执行。关于圆括号与解构赋值的关系,参见下文。

    (2)解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式。

    ({} = [true, false]);
    ({} = 'abc');
    ({} = []);
    
    • 1
    • 2
    • 3

    上面的表达式虽然毫无意义,但是语法是合法的,可以执行。

    (3)由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。

    let arr = [1, 2, 3];
    let {0 : first, [arr.length - 1] : last} = arr;
    first // 1
    last // 3
    
    • 1
    • 2
    • 3
    • 4

    上面代码对数组进行对象解构。数组arr0键对应的值是1[arr.length - 1]就是2键,对应的值是3

    3.字符串的解构赋值

    既可以用数组的形式来解构赋值,也可以用对象的形式来解构赋值。

    // 数组形式解构赋值
    const [a, b, , , c] = 'hello';
    console.log(a, b, c);	// h e o
    
    // 对象形式解构赋值
    const {0: a, 1: b, 4: o, length} = 'hello';
    console.log(a, b, o, length);	// h e o 5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.数值和布尔值的解构赋值

    只能按照对象的形式来解构赋值。

    (会先自动将等号右边的值转为对象)

    // 先来复习一下将数值和布尔值转化为对象
    console.log(new Number(123));
    console.log(new Boolean(true));
    // 转化后的对象里没有任何的属性(没有 123 这个属性,也没有 true 这个属性)和方法,
    // 所有的属性和方法都在它的继承 __proto__ 中,比如 toString 方法就是继承来的。
    
    // 里面的值只能是默认值,继承的方法倒是可以取到
    const {a = 1, toString} = 123;
    console.log(a, toString);	// 1 [Function: toString]
    
    // 里面的值只能是默认值,继承的方法倒是可以取到
    const {b = 1, toString} = true;
    console.log(b, toString);	// 1 [Function: toString]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    知道有这回事即可,一般都用不到,因为没太大意义。

    5. undefined 和 null 没有解构赋值

    由于 undefined 和 null 无法转为对象,所以对它们进行解构赋值,都会报错。

    6.小结

    本节讲解了 ES6 解构赋值的使用方法,总结下来一共有以下几点:

    1. 解构赋值一般针对对象和数组,如果解构对象是 undefined 或是 null 都会报错;
    2. 默认值的生效条件是,只有当解构的对象的值是严格模式下的 undefined 的情况下,默认值才会生效;
    3. 可以不借助中间变量来交换两个值;
    4. 在解构复杂的数据解构时,注意声明的对象要和目标的对象有着相同的解构形式,才能去解构目标对象。
  • 相关阅读:
    gin框架中使用websocket发送消息及群聊
    【通信误码】python实现-附ChatGPT解析
    代码优化技巧
    HTML+CSS+JavaScript七夕情人节表白网页【樱花雨3D相册】超好看
    BPF:BCC工具 funccount 统计内核函数调用(内核函数、跟踪点USDT探针)认知
    Github 2024-06-20 Go开源项目日报 Top10
    课设总结【硬件课设】
    【JavaScript复习十】数组入门知识
    第87步 时间序列建模实战:LSTM回归建模
    whee: 美图秀秀出品AI绘画图片创作工具平台
  • 原文地址:https://blog.csdn.net/DSelegent/article/details/126558537