zoukankan      html  css  js  c++  java
  • ES6(变量的解构赋值)

         以前给变量赋值都是var a = 10这样直接赋值,如今ES6提供了一种方法来赋值,即解构赋值,解构赋值是通过按照一定的模式,从数组和对象里读取值,然后对变量赋值变量的解构赋值包括:数组,对象,字符串,数值,布尔值,函数参数。

          【1】数组的解构赋值

    var  [a , b , c] = [1 , 2 , 3];

          在ES6中可以直接这么对变量赋值,这种写法被称为“模式匹配”,只要两边的模式一样就可以进行赋值。例如:

    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,...b] = [1,2,3];  // a = 1   ...b =  [2,3]
    let  [a,b,...c] = [1];  //a = 1  b = undefined   ...c = []

         上面最后一个赋值,b的值为undefined,这就是解构不成功的结果。

         如果等号的右边不是数组,那么将会报错,譬如:

    let [a] = 1;
    let [a] = false;
    let [a] = undefined;
    let [a] = null;
    let [a] = NaN;
    let [a] = {};

        会报错是因为右边的值转为对象后不具有Iterator接口(前五个例子),还有本身就不具有Iterator接口(最后一个例子)。这说明了只要某种数据结构具有Iterator接口,都可以使用数组形式进行解构赋值。

        解构赋值允许指定默认值,不过需要注意的是,只有变量严格等于undefined,默认值才会生效。比如:

    var  [x = 1] = [undefined];  // x =1
    var  [x = 1] = [null];  // x = null

        如果默认值是一个表达式的话,只有在变量取不到值时才会执行这个表达式。

        默认值还可以引用解构赋值的其他变量,不过前提是,这个被引用的变量必须已经声明了,不然会报错,比如:

    let  [x = 1, y = x] = []; // x =1  y =1
    let  [x = 1, y = x] = [2]; // x = 2 y = 2
    let  [x = 1, y = x] = [1,2] // x = 1 y = 2
    let  [x = y, y = 1] = []; //referenceError

       【2】对象的解构赋值

           对象的解构与数组有一个重要的不同。即数组的元素是按次序排列的,变量的取值由它的位置所决定;而对象的属性不需要按次序排列,但需要注意的是,变量必须与属性同名,只有这样才能取到正确的值。比如:

    var { bar, foo } = { foo: "aaa", bar: "bbb" }; //  foo = "aaa"   bar = "bbb"
    var { baz } = { foo: "aaa", bar: "bbb" }; //  baz = undefined

          如果变量名与属性名不一样,但又想取到值,可以这么写:

    var { foo: baz } = { foo: 'aaa', bar: 'bbb' };  // baz = "aaa"   // foo  error: foo is not defined

         通过这个例子,我们可以知道其实真正被赋值的是变量baz,而不是模式foo,也就是说对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。不过需要注意的是,采用这种写法时,变量的声明和赋值是一体的,对于let和const来说,变量是不能重新声明的,所以一旦赋值的变量以前声明过,就会报错。例如:

    let foo;
    let {foo} = {foo: 1}; // SyntaxError: Duplicate declaration "foo"

        不过如果变量是var 声明的就不会出现这个错误,因为var声明的变量允许重复声明,在去掉第二个let 之后就可以成功解构,例如:

    let foo;
    ({foo} = {foo: 1}); //  成功

       但是一定要记得加上(),这个是必须的,因为解析器会将起首的大括号,理解成一个代码块,而不是赋值语句。所以将一个已经声明的变量用于解构赋值就需要添加()。

       解构也可以用于嵌套结构的对象。比如:

    var node = {
        loc: {
          start: {
             line: 1,
             column: 5
          }
        }
    };
    var { loc: { start: { line }} } = node;
    line // 1
    loc // error: loc is undefined
    start // error: start is undefined

        只有line是变量,所以可以被赋值,而loc和start是模式,所以不会被赋值。

        对象的解构也可以指定默认值,和数组一样,默认值生效的前提是,对象的属性值严格等于undefined。

       【3】字符串的解构赋值

             当使用字符串进行解构赋值时,字符串就被转换成了一个类似数组的对象,这个对象有一个length属性,也可以对这个属性解构赋值。比如:

    const [a, b, c, d, e] = 'hello'; // a = "h"  b = "e"  c = "l"  d = "l"  e = "o"
    let {length : len} = 'hello';  // len = 5

       【4】 数值和布尔值的解构赋值

             当解构赋值数值和布尔值时,会先转化为对象。那么从这里我们就知道解构赋值的规则是,只要等号右边的值不是对象,就先将其转为对象。注意undefined和null不能转为对象,所以无法对它们进行解构赋值,不然会报错,例如:

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

       【5】 函数参数的解构赋值

                函数的参数不仅可以解构赋值,还可以使用默认值。而且undefined会触发函数参数的默认值。

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

             如果是为函数move的参数指定默认值,而不是为变量x和y指定默认值,那么就会得到不一样的结果,如:

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

       圆括号问题

           在解构赋值的某些情况下,我们需要使用到圆括号,那么在什么情况下可以用圆括号,什么情况下不能用圆括号。

          可以使用圆括号:[1]: 赋值语句的非模式部分,可以使用圆括号。

          不可以使用圆括号:[1]:变量声明语句中,不能带有圆括号。

                                   [2]:函数参数中,模式不能带有圆括号。

                                   [3]:赋值语句中,不能将整个模式,或嵌套模式中的一层,放在圆括号之中。

         变量的解构赋值在什么时候用呢——[1]:交换变量的值;

                                                      [2]:从函数返回多个值;

                                                      [3]:函数参数的定义;

                                                      [4]:提取 JSON 数据;

                                                      [5]:函数参数的默认值;

                                                      [6]:遍历 Map 结构;

                                                      [7]:输入模块的指定方法。

  • 相关阅读:
    mongoDB
    邮箱认证
    Django中开启事务的两种方式
    总结
    __new__和__init__和__call__方法理解
    jupyter
    text()和html()区别
    django模型中auto_now和auto_now_add的区别
    ajax嵌套陷阱
    模板内置函数(HTML)
  • 原文地址:https://www.cnblogs.com/yezi-dream/p/6249310.html
Copyright © 2011-2022 走看看