美文网首页
2、变量的解构赋值

2、变量的解构赋值

作者: Elevens_regret | 来源:发表于2017-03-09 17:25 被阅读0次

    1、数组的解构赋值

    基本用法

    本质上,只要等号两边的模式相同,左边的变量就会被赋予对应的值,...表示将剩下的值赋予此变量,无剩余则赋值为空数组,解构不成功则赋值为undefined。等号两边都要为数组。

    let a = 1;
    let b = 2;
    let c = 3;
    //ES6可以写成
    let [a, b, c] = [1, 2, 3];
    
    //多重数组的例子
    let [a, [[b], c]] = [1, [[2], 3]];
    a // 1
    b // 2
    c // 3
    
    //对应位置赋予对应的值
    let [ , , c] = ["1", "2", "3"];
    c // "3"
    let [a, , c] = [1, 2, 3];
    a // 1
    c // 3
    
    //...语法有剩余值时
    let [a, ...z] = [1, 2, 3, 4];
    a // 1
    z // [2, 3, 4]
    
    //...语法无剩余值时
    let [a, b, ...z] = ['a'];
    a // "a"
    b // undefined
    z // [] 空数组
    

    默认值

    解构赋值可以使用默认值,当且仅当变量的值全等于(===)undefined时,才会使用默认值,即使是等于null时也不会使用默认值。

    let [a = 1] = []; a // 1
    
    let [a, b = '2'] = ['1']; // a='1', b='2'
    let [a, b = '2'] = ['1', undefined]; // a='1', b='2'
    
    let [x = 1] = [null]; x // null
    

    当默认值是一个表达式的时候(例如一个行数表达式),若变量能够取到值(值不全等于undefined),则表达式不会执行。

    function f() {
      console.log('a');
    }
    let [x = f()] = [1]; //f()不会执行,y=1
    

    默认值可以引用解构赋值中的其他变量,前提是变量已经声明

    let [x = 1, y = x] = [1, 2]; // x=1; y=2
    let [x = y, y = 1] = [];     // y在x引用的时候还没有声明,所以报错。
    

    2、对象的解构赋值

    与数组的解构赋值不同的是,数组解构是按照元素的次序赋值的,而对象则不受次序的影响,变量必须与属性同名,才能被赋值,没有同名属性则赋值为undefined。

    let { pro1, pro2 } = { pro1: "1", pro2: "2" };
    pro1 // "1"
    pro2 // "2"
    //上述表述是一种缩写,其本质是
    let { pro1:pro1, pro2:pro2 } = { pro1: "1", pro2: "2" };
    
    //在等号左边时,:号左边的pro1和pro2是定义匹配模式,真正被赋值的是:号右边的pro1和pro2,当匹配模式和属性名同名时,可以使用缩写
    let { proa:prox, prob:proy } = { proa: "1", prob: "2" };
    prox //"1"
    proy //"2"
    

    对象解构中左边的变量一定是由:组成的一对匹配模式和属性名。只有一个匹配模式时,一定是匹配模式和属性名相同,使用了简写。

    var obj= {
      a: {
        b: {
          c: 1,
          d: 2
        }
      }
    };
    var { a: { b: { c }} } = obj;
    a // 报错,a在:左边,是匹配模式,不是属性名
    b // 报错,b在:左边,是匹配模式,不是属性名
    c // 1
    

    对象的解构赋值同样支持默认值,规则与数组的解构相似:

    1. 当且仅当变量值全等于(===)undefined时,才会取默认值。
    2. 如果解构失败,变量的值等于undefined。

    当大括号位于本行的首位时,需要加上小括号,因为 { } 表示一个代码块,不是一个单独的语句。

    let x;
    {x} = {x: 1}; // 语法错误,左边是一个代码块,不是一个声明。
    
    ({x} = {x: 1}); // 加上小括号,成为一个单独的语句,语法正确。
    

    当变量名与现有对象的属性名相同时,可以直接使用对象赋值。

    let { log, sin, cos } = Math;
    log // Math.log
    sin // Math.sin
    cos // Math.cos
    

    因为在JavaScript中,数组是特殊的对象,所以可以用数组进行对象属性的结构。

    let arr = [1, 2, 3];
    let {0 : a, [arr.length - 1] : b} = arr;
    a // 1
    b // 3
    

    3、字符串的解构赋值

    字符串进行结构赋值时,被转化为了一个类似数组的对象。

    const [a, b, c, d, e] = 'hello';
    a // 'h'
    let {length : len} = 'hello';
    len // 5   因为右边'hello'字符串被转化为了一个类似数组的对象,具有length属性,所以可以直接赋值给左边同名的匹配模式。
    

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

    解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

    let {toString: s} = 123;
    s === Number.prototype.toString // true
    
    let {toString: s} = true;
    s === Boolean.prototype.toString // true
    

    解构赋值的规则是,只要右边不是对象或者数组,就将其转化为对象,再进行匹配赋值。
    因为undefined和null不能转化为对象,所以单独将这两个值当做右边的值进行匹配赋值时会报错。

    let { prop: x } = undefined; // 报错
    let { prop: y } = null; // 报错
    

    5、函数参数的解构赋值

    function add([x, y]){
      return x + y;
    }
    add([1,2]); // 传输数组参数相当于执行了 [x,y]=[1,2];x和y被分别赋值为1和2
    

    函数参数的解构也可以使用默认值,但下面两种情况不同:

    function move({x = 0, y = 0} = {}) {
      return [x, y];
    } 
    

    这种方式表示x和y没有给定值时默认值为0,x和y是分开赋值的,只要参数中存在没有传入的项,就使用其默认值。
    即只要某一项参数不存在,就一定会使用其默认值。

    function move({x, y} = { x: 0, y: 0 }) {
      return [x, y];
    } 
    

    这种方式指定的是整个参数的默认值,而不是单独指定x和y,x和y是当做一个整体。只有当完全不传任何参数时,才会使用默认值(传入空对象也不会使用默认值),无论是单独传了x参数,还是单独传了y参数,未传的项都不会使用默认值。
    即只要存在参数,且参数不全等于(===)undefined,就一定不会使用默认值。


    6、圆括号问题

    ES6的规则是:只要有可能导致解构歧义,就不得使用圆括号。
    所以,在非必要情况下,没有必要添加圆括号(事实上大部分圆括号都是没有必要添加的)。

    不允许使用圆括号的情况
    1. 声明语句中不允许使用圆括号
    2. 函数参数中,匹配模式不允许使用圆括号,因为函数参数也属于变量声明
    3. 不能将整个模式或嵌套中的某一整层放在圆括号当中。

    7、解构用途

    交换变量的值
    let x = 1;
    let y = 2;
    
    [x, y] = [y, x]; // 简洁易懂的交换
    

    从函数返回多个值

    当函数需要返回多个值时,将这些值组成一个数组或对象,返回这个数组或对象,然后再用解构赋值来取的各项的值。

    // 返回一个数组
    
    function example() {
      return [1, 2, 3];
    }
    let [a, b, c] = example();
    
    // 返回一个对象
    
    function example() {
      return {
        foo: 1,
        bar: 2
      };
    }
    let { foo, bar } = example();
    

    函数参数的定义(包括函数参数使用默认值)
    // 参数是一组有次序的值
    function f([x, y, z]) { ... }
    f([1, 2, 3]);
    
    // 参数是一组无次序的值
    function f({x=0, y=0, z=0}) { ... }
    f({z: 3, y: 2, x: 1});
    

    提取JSON数据
    let jsonData = {
      id: 42,
      status: "OK",
      data: [867, 5309]
    };
    
    let { id, status, data: number } = jsonData;
    
    console.log(id, status, number);
    // 42, "OK", [867, 5309]
    

    相关文章

      网友评论

          本文标题:2、变量的解构赋值

          本文链接:https://www.haomeiwen.com/subject/fhowgttx.html