ES6新语法之---解构(4)

ES6中引入了新语法--解构,我们把这个功能看做是结构化赋值,会更容易理解些。

第一部分:ES5数组、对象结构

  1.1:数组结构

        function foo() {
            return [1, 2, 3]
        }
        var tmp = foo(),
            a = tmp[0],
            b = tmp[1],
            c = tmp[2];
        console.log(a, b, c)

  我们构造了一个手动赋值,把foo()返回数组中的值赋给独立变量a、b和c,为了实现这一点我们需要一个临时变量tmp

  1.2:对象结构

        function foo() {
            return {
                x: 4,
                y: 5,
                z: 6
            }
        }
        var tmp = foo(),
            a = tmp.x,
            b = tmp.y,
            c = tmp.z;
        console.log(a, b, c)

  这里实现对象的赋值,依然使用了临时变量tmp。

  ES6为解构新增了一个专门语法,专用于数组解构和对象解构,消除了前面实现解构中的临时变量tmp,使代码更简洁。

第二部分:ES6解构

  2.1:数组、对象解构

        function foo() {
            return [1, 2, 3]
        }
        function bar() {
            return {
                x: 4,
                y: 5,
                z: 6
            }
        }
        var [a, b, c] = foo();
        var {x: x, y: y, z: z} = foo()
        console.log(a, b, c)
        console.log(x, y, z)

  左侧的[a, b, c]和{x: x, y: y, z: z}更像一种数据组成结构把右边的数据按照左边的结构赋值到对应的变量中

  2.2:结构中当属性名和要赋的变量名相同的时候,可以简写

        function bar() {
            return {
                x: 4,
                y: 5,
                z: 6
            }
        }
        var {x, y, z} = bar()  //这里我们可简写
        console.log(x, y, z)

  那么这里具体是省略了属性'x:',还是省略了赋值部分':x',其实这里省略了属性部分'x:'

  但并不是说有了简化方式,之前的冗长形式就无用了,它支持把属性赋给非同名变量

        function bar() {
            return {
                x: 4,
                y: 5,
                z: 6
            }
        }
        var {x: bam, y: baz, z: bap} = bar()
        console.log(bam, baz, bap)      //这里讲bar()结果中的x,y,z分别赋给了bam, baz, bap。
        console.log(x, y, z)            //ReferenceError: x is not defined    

  2.3不仅仅用于声明

  上例中都是在var(let/const)声明中使用了解构赋值,但其赋值解构是一个通用的赋值操作,不只是应用在声明中。

        function foo() {
            return [1, 2, 3]
        }
        function bar() {
            return {
                x: 4,
                y: 5,
                z: 6
            }
        }
        var a, b, c, x, y, z
        [a, b, c] = foo();      //我们直接可以使用解构进行赋值操作。
        ({x, y, z} = bar());    //如果没有()那么{}会被识别成代码块而非对象。
        console.log(a, b, c);
        console.log(x, y, z);

  赋值表达式并不必须是变量标识符。任何合法的赋值表达式都可以

        var o = {};
       [o.a, o.b, o.c] = foo();         //这里可以是o的属性,并不必须是声明的变量名。
       ({x: o.x, y: o.y, z: o.z} = bar());
       console.log(o.a, o.b, o.c)
       console.log(o.x, o.y, o.z)

  或者使用计算出的属性表达式

        var which = 'x',
            o = {};
        ({[which]: o[which]} = bar())   //[which]是计算出的属性,结果是x
        console.log(o.x)

  可以使用一般的赋值创建对象映射

        //对象映射为对象
        var o1 = {a: 1, b: 2, c:3},
            o2 = {};
        ({a: o2.x, b: o2.y, c: o2.z} = o1)
        console.log(o2.x, o2.y, o2.z);      //1, 2, 3

        //对象映射为数组
        var o1 = {a: 1, b: 2, c:3},
            a2 = [];
        ({a: a2[0], b: a2[1], c: a2[2]} = o1)
        console.log(a2);      //[1, 2, 3]

        //数组映射为对象
        var a1 = [1, 2, 3],
            o2 = {};
        [o2.a, o2.b, o2.c] = a1;
        console.log(o2)       //{a: 1, b: 2, c: 3}
    
     //数组重排序到另一个  
      var a1 = [1, 2, 3],
      a2 = [];
      [a2[2], a2[0], a2[1]] = a1;
      console.log(a2) // [2, 3, 1]

  不使用临时变量,完成两个变量值交换的问题。

        var x = 10, y = 20;
        [y, x] = [x, y]
        console.log(x, y)   //20, 10    

  2.4重复赋值

  2.4.1对象解构允许多次列出同一个源属性:

        var {a: x, a: y} = {a: 1}
        console.log(x, y)   // 1, 1

        var {a: {x: X, x: Y}} = {a: {x: 1}}  //这里我们不仅能得到a本身的值,还能得到a中子对象属性x的值。
        console.log(X, Y);    // {x: 1} , 1, 1

        ({a: X, a: Y, a: [z]} = {a: [1]});
        X.push(2)
        Y[0] = 10;
        console.log(X, Y, z)    //[10, 2] , [10,2] 1

  2.4.2解构赋值表达式

  对象或数组解构的复制表达式的完成值是所有右侧对象/数组的值

         //对象的解构赋值表达式
        var o = {a: 1, b: 2, c: 3},
            a, b, c, p;
        p = {a, b, c} = o;      // {a, b, c} = o;完成值是o, 那么p就是o一份拷贝
        console.log(a, b, c);   // 1, 2, 3
        console.log(p === o);   //true

         //数组的解构赋值表达式
         var o1 = [1, 2, 3],
            a1, b1, c1, p1;
        p1 = [a1, b1, c1] = o1;      // {a1, b1, c1} = o1;完成值是o1, 那么p1就是o1一份拷贝
        console.log(a1, b1, c1);   // 1, 2, 3
        console.log(p1 === o1);   //true

  通过持有对象/数组的值作为完成值,可以把解构赋值表达式组成链

        var o = {a: 1, b: 2, c: 3},
           p = [4, 5, 6],
           a, b, c, x, y, z;
        ({a} = {b, c} = o);     // {b, c} = o的结果依旧是对象o,继续使用{a} = o,这样就组成链
        [x, y] = [z] = p;
        console.log(a, b, c)
        console.log(x, y, z)    

  2.5数组/对象中部分值赋值解构

  2.5.1只赋值结构部分值。

        var [, b] = foo();     //返回的1,2丢掉了
         var {x, z} = bar();    //返回的5丢掉
         console.log(b, x, z);    

   为比分解出来的更多值赋值

     //foo()和bar()的方法在前面已经提到,不再重复    
     var [, ,c, d] = foo(); var {w, z} = bar(); console.log(c, z); // 3, 6 console.log(d, w); // 多余的值会被赋值为:undefined, undefined

  2.5.2 默认值赋值

  与默认函数参数值类似,结构也可以提供一个用来赋值的默认值

        var [a = 3, b = 6, c = 9, d = 12] = foo();
        var {x = 5, y = 10, z = 15, w = 20} = bar();
        console.log(a, b, c, d);    //1, 2, 3, 12,其中foo()返回值没有d就是用默认值。
        console.log(x, y, z, w);    // 4, 5, 6, 20 ,w一样

        //赋值表达式
        var {x, y, z, w: W = 20} = bar();
        console.log(x, y, z, WW)

  2.5.3 解构参数

  1>函数参数为数组/对象的解构

        //参数为数组的解构赋值
        function foo([x, y]) {
            console.log(x, y)
        }
        foo([1, 2]);    // 1, 2
        foo([1]);       // 1, undefined
        foo([]);        // undefined, undefined

        //参数为对象的解构赋值
        function foo({x, y}) {
            console.log(x, y)
        }
        foo({y: 1, x: 2});    // 2, 1
        foo({y: 2});       // undefined, 2
        foo({});        // undefined, undefined

  2>解构默认值和函数默认值

        function fun({x = 10} = {}, {y} = {y: 10} ) {
            console.log(x, y)
        }
        fun();  //10, 10

        fun({}, {})     //10, undefined  

  这里输出的结果是否和期望的一样呢?那么结果为什么是这样呢?

  理解:{y} = {y : 10},这种情况如果第一个参数省略或者传入undefined,就会使用{y : 10}默认对象。

     而对于{x = 10} = {},其中的{x = 10}类似解构默认值,如果第一个参数省略或者传入undefined,就会使用{}对象,接着{}会按照{x = 10}的结构进行解构,没有传入任何值就用x的默认值10。

总结:结构为我们开发带了很多便利,但并不是说应该肆无忌惮的使用,而是应该在合适的场景使用,这样才能真正提高我们的开发效率。

posted @ 2018-05-05 16:21  诸葛不亮  阅读(988)  评论(0编辑  收藏  举报