web前端—前端三剑客之JS-ES6(2):解构赋值

目录

数组的解构赋值

注意点

解析不成功与不完全解析

解析赋值要求

指定默认值

惰性求值

 对象的解构赋值

示例 

嵌套

字符串的解构赋值

数值和布尔值的解构赋值

函数参数的解构赋值 

解构赋值的常见应用场景

变量交换

从函数返回多个值

函数参数的定义

提取 JSON 数据


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

数组的解构赋值

注意点

1、赋值等号的左右侧的数组结构需要一致,这个叫做”模式匹配”

        let [a,b,c] = [1,2,3];
        console.log(a,b,c);    // 结果:1 2 3

        let [a1,[a2,a3]] = [11,[22,33]];
        console.log(a1,a2,a3);   // 结果:11 22 33

2、如果左右两侧的变量数与数值数的数量不匹配, 那么就直接跳过缺失部分( 左边的跳过了, 右侧相应位置的也要跳过)

        let [,,td] = ['n','p','m'];
        console.log(td);   // 结果:m

        let [x,,z] = [24,25,26];
        console.log(x,z);     // 结果:24 26

3、如果左侧某个变量前有三个小点, 那么意味着右侧对应位置及以后的所有数值将组合成一个数组,赋值给左侧的该变量,且左侧必须是最后一个变量才可以在前面加三个小点,否则报错

        let [start,...end] = [1,2,3,4,5];
        console.log(start,end);   // 结果:start 1 ;end [2, 3, 4, 5]

        let [x1,y1,y2,...z1] = ['hello'];
        console.log(x1,y1,y2,z1);   // 结果:hello   undefined  undefined   []

        // let [x2,x3,...x4,x5] = ['h','e','l','l','o'];   // 报错:Uncaught SyntaxError: Rest element must be last element

解析不成功与不完全解析

解析不成功

等号左边的变量比等号右边的值多的时候就会解析不成功,对应的变量的值就等于undefined。

        let [x1,y1,y2,...z1] = ['hello'];
        console.log(x1,y1,y2,z1);   // 结果:hello   undefined  undefined   []

        let [p1,p2] = [1];
        console.log(p1,p2);   // 结果:1 undefined

不完全解析

等号左边的模式,只匹配一部分的等号右边的数组

        let [a, [b],c] = [1,[2,3,4],5];
        console.log(a,b,c);   // 结果:1  2  5

解析赋值要求

赋值(等号的右边)必须是可遍历的结构,否则将会报错。

// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

指定默认值

解构赋值允许指定默认值。注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当右侧一个数组成员严格等于undefined,默认值才会生效。 (因为要是采用==,那么就会产生数据类型转换了)

        console.log(c1,c2,c3);    // 结果:12  undefined  3

        let [d1='12',d2] = [1,4];
        console.log(d1,d2);    // 结果:1  4

注意1:如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined

        let [e1 = 66] = [undefined];
        console.log(e1);      // 结果:66
        let [e2 = 66] = [null];
        console.log(e2);     // 结果:null
        let [e3 = 66] = [NaN];
        console.log(e3);     // 结果:NaN

 注意2:默认值可以引用解构赋值的其他变量,但该变量必须已经声明

        let [g1 = 7, g2 = g1] = [];
        console.log(g1,g2);   // 结果:7  7 

        let [g3 = 7, g4 = g3] = [4,5];
        console.log(g3,g4);   // 结果:4  5 

        let [g5 = 7, g6 = g5] = [3];
        console.log(g5,g6);   // 结果:3  3

        let [g7 = g8, g8 = 7] = [];   // 报错:Uncaught ReferenceError: Cannot access 'g8' before initialization

惰性求值

如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。

        function fc() {
            console.log('惰性求值');
        }

        let [f1 = fc()] = 'hehe';
        console.log(f1);    // 结果:h
        let [f2 = fc()] = '';     //  结果调用fc函数:惰性求值

对象的解构赋值

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值

示例 

例1:等号左边的两个变量的次序,与等号右边两个同名属性的次序不一致,但是对取值完全没有影响

        let {a1,a2} = {a1:'1',a2:'2'};
        console.log(a2,a1);    // 结果:2  1

例2:变量没有对应的同名属性,导致取不到值,最后等于undefined

        let {b1} = {b2:'3',b3:4};
        console.log(b1);    // 结果:undefined

例3:对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者,前者是匹配模式,后面的才是变量,使用的时候取后面的变量,否则报错

        let {c2:cn} = {c2:'3',c3:4};
        console.log(cn);    // 结果:3
        // console.log(c2);    // 结果:Uncaught ReferenceError: c2 is not defined

例4:对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量

        let {log} = console;
        log('呵呵呵!')    // 结果: 呵呵呵!

        let {cos,sin,log,tanh}=Math;
        console.log(tanh(45));    // 结果:1

例5:由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构

        let o = [1,3,5,7,9];
        let {0:first,[o.length-1]:last} = o;
        console.log(first,last);    // 结果:1  9 

 例6:如果要将一个已经声明的变量用于解构赋值,必须非常小心。左侧代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块(最简单的块级作用域),从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。

嵌套

与数组一样,解构也可以用于嵌套结构的对象。注意,:前面的是匹配模式,而不是变量,如celebrity1和celebrity2,因此不会被赋值。[]数组变量可以是自定义,{}匹配的变量必须和对象值中的一致


        let obj = {
            celebrity1:{
                name1:'墨子'
            },
            celebrity2:[
            {name2:'荀子',era:'战国'}
            ]
        }

        let {celebrity1,celebrity1:{name1},celebrity2:[{name2,era}]} = obj;
        console.log(celebrity1,name1,name2,era);    // 结果:{name1: "墨子"}   "墨子"   "荀子"   "战国"

字符串的解构赋值

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。 类似数组的对象都有一个length属性,因此还可以对这个属性解构赋

        let a = '1234567890';
        let {length:len} = a;
        console.log(len);    // 结果:10
        
        let [b1,b2,b3,b4,b5] = a;
        console.log(b1,b4);    // 结果:1  4 

数值和布尔值的解构赋值

解构赋值的规则是:只要等号右边的值不是对象或数组,就先将其转为对象。 由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

        let {p1 : x} = true;
        console.log(x);     // 结果:undefined
        let {p2 : y} = null;    // 报错:Uncaught TypeError: Cannot destructure property 'p2' of 'null' as it is null.
        let {p3 : z} = undefined;   // 报错:Uncaught TypeError: Cannot destructure property 'p3' of 'undefined' as it is undefined.

函数参数的解构赋值 

函数参数的解构也可以使用默认值。

这里有两个步骤:

1、对函数里面的参数进行解构赋值, 得到的结果就是{x=0,y=0}

2、函数调用时进行数据传参, 如果传入的参数可以正常进行解构赋值,那么就使用传进的参数否则,就调用默认值

左侧代码是为函数move的参数指定默认值,而不是为变量x和y指定默认值,所以会得到与前一种写法不同的结果。所以函数的默认参数是{x=0,y=0},一旦这个函数在执行时传入了其他参数, 那么这个默认的参数就不起作用,只有当函数在执行不传入任何参数, 这个默认参数才有作用

解构赋值的常见应用场景

变量交换

      // 新方法:解构赋值
      let x = 1;
      let y = 2;
      [x,y] = [y,x];
      console.log(x,y);
      
      // 1、用一个中间变量
      let z = x;
      x = y;
      y = z;
      console.log(x,y);

      // 2、异或
      x = x^y;
      y = x^y;
      x = x^y;
      console.log(x,y);
      // 3、算术运算符 - +
      x = x + y;
      y = x - y;
      x = x - y
      console.log(x,y);

从函数返回多个值

        function fn() {
          return [1, 2, 3];
        }
        
        // let [a, b, c] = fn();
        // console.log(b);   // 结果:2

        let c = fn();
        let a = c[0];
        let b = c[1];
        let d = c[2];
        console.log(c);   // 结果:[1, 2, 3]
        console.log(a);   // 结果:1
        console.log(b);   // 结果:2
        console.log(d);   // 结果:3

函数参数的定义

解构赋值可以方便地将一组参数与变量名对应起来 

 

提取 JSON 数据

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值