ES6入门三:解构

  • 数组解构
  • 对象解构
  • 声明与解构相关的问题
  • 解构与重复赋值
  • 按需解构
  • 默认值赋值
  • 解构参数

 解构(destructuring):结构化赋值

解构通常被看作ES6的一个结构化赋值方法,可以通过解构将数组元素或者对象属性拆分出来,成为单个变量。并且在命名相同的情况下可以实现名称复用,以达到减少代码量的目的,解构的基本目的就是减少代码量。

ES6之前从数组中拆分元素然后赋值给变量怎么做?

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

采用ES6的解构数组的代码:

var [a, b, c] = foo(); 

ES6之前从对象中拆分属性作为变量转码做?

 1 function bar(){
 2     return {
 3         x:4,
 4         y:5,
 5         z:6
 6     }
 7 }
 8 var tmp = bar(),
 9     x = tmp.x, y = tmp.y, z = tmp.z;
10 console.log(x, y, z); //4 5 6

ES6解构对象属性的代码:

1 var {x:x, y:y, z:z} = bar(); //这行代码还可以简写:var {x, y, z} = bar();
2 console.log(x, y, z); //4 5 6

 对象属性赋值模式:

看到上面的解构语法,第一个疑问就是数组和对象是通过什么方式将元素和属性值赋给变量的呢?背后的复杂逻辑就不再这里探讨,值得我们关注的是,表达式中的那个是变量名称,那个是元素或者属性的引用?当看到数组的解构时,还比较好理解:

var [a, b, c] = foo(); 

从示例中可以看到a, b, c是变量的名称,而它们实际上是通过中括号“[]”的数组索引将foo()方法执行方法的对应的索引的值,赋值给对应位置的变量。而这样我们就可以推断出,对象解构在解构表达中左边的“x:”表示的是对象的属性值引用,“x”是变量,简写的方式在示例的注释中已经写出来了,意思就是变量复用对象的属性名作为变量名。如果是要通过解构来声明全新的变量名呢?

let {x:bam, y:baz, z:bap} = bar();

这就是对象属性赋值模式,因为左边的结构很像一个对象,但是结构的语法却是从左向右赋值,不是对象自变量中的右边向左边的属性名赋值。

 声明与解构相关的一些问题:

在通常的开发中,我们都喜欢将变量名称写在作用域的第一排,这种书写方式有时候甚至被写入开发手册中,作为开发代码的书写标准,这时候对象结构就需要加上小括号,避免“{}”被解析为一个块级作用域:

1 var a, b, c, x, y, z;
2 [a, b, c] = foo();
3 ({x, y, z} = bar()); // 对象解构时这种情况要记得写小括号

 解构时可以使用计算属性:

 比如需要解构对象中的属性添加到另一个对象中,可以使用计算属性的方式来实现:

1 var which = "x",
2     o = {};
3 ({[which]:o[which]} = bar());// 本质上同等与({x:0.x})
4 console.log(o.x); // 4

 解构与重复赋值:

通过上面的一系列解构传值逻辑,重复使用解构对象的属性值就很简单理解了,看下面:

1 var {s:m, s:n} = {s:10}; //重复使用s属性值分别赋给m, n
2 console.log(m, n);// 10 10

接着玩一些更复杂的重复赋值的解构:

1 var {a:{x: X, x: Y},a} = {a: {x: 1}};
2 //分析:
3 // 第一步
4 // ({x: X, x:Y} = {x: 1}); a = {x:1};
5 // 第二部
6 // X = 1, Y = 1,

再来一个数组的重复赋值解构:

 1 var {a:X, a:Y, a:[Z]} = {a:[1]};
 2 // 分析
 3 // 第一步
 4 // X = [1], Y = [1], ([Z] = [1]);
 5 // 第二部
 6 // Z = 1;
 7 console.log(X,Y,Z); // [1] [1] 1
 8 X[0] = 10;
 9 Y.push(2);
10 console.log(X,Y,Z); // [10,2] [10,2] 1

通过上面这个示例也说明了解构出来的应用值类型的数据只是简单的引用赋值,不是克隆,一档有一个引用将其中的属性值修改,其他所有引用都会被作用到。

 按需解构:

按下解构就是只解构想要的属性和元素,并且可以允许出现没有相匹配的属性和元素,这个对应的变量会被声明但没有赋值。

1 var [,,c,d] = [1,2,3];
2 var {w,z} = {x:10,y:20,z:30};
3 console.log(c,d); // 3 undefined
4 console.log(w,z); // undefined 30

 默认值赋值:

有了上面的不匹配现象,就让我想起了ES6给方法提供的默认参数,在解构中也可以实现默认值:

1 var [a = 3, b = 6, c = 9, d = 12] = [1, 2, 3];
2 console.log(a, b, c, d); // 1 2 3 12
3 var {x, y, z, w = 50} = {x:10, y:20, z:30}
4 console.log(x, y, z, w); //10 20 30 50

 解构参数:

起始本质上解构就是一种变量声明与赋值行为,所以这种操作当然也就可以被放到方法的参数里面来,这让传值变得非常方便,也省去了麻烦的参数类型的转换和拆解。

1 function ([x,y]){
2     console.log(x,y);
3 }
4 foo([1,2]);// 1 2

形参作为变量接收,实参是被解构的对象。

最后来一个有意思的算法题,使用解构实现两个变量交换值:

1 var a = 10, b = {value:"B"};
2 [a, b] = [b, a];
3 console.log(a, b); //{value:10} 10

 最后可以综合的使用解构的这些语法来实现非常复杂的应用,比如解构默认值 + 参数默认值实现传参,嵌套默认:解构重组,详细可以参考《你不知道的JS》下卷P86~P90。

posted @ 2019-08-14 02:36  他乡踏雪  阅读(379)  评论(0编辑  收藏  举报