ES6语法——解构赋值

1_什么是解构赋值

  (1) 解构赋值,即对某种结构进行解析,然后将解析出来的值赋值给相关的变量,常见的有数组、对象、字符串的解构赋值等。一般用解构赋值的多数是数组和对象这两种数据类型。
  (2) 解构赋值本质上相当于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
  (3) 解构赋值本质上是浅拷贝,只是对对象的引用,而不是对象的副本


  (这里的左边是数组右边是对象 数字7会进行转换成相应的对象new Number(7) 。等式两边在模式上不匹配,所以会报错)
  (3) ES6为我们推出了解构赋值这个特性。我们可以更简单的获取对象或者数组中的数据。

2_解构赋值的分类

(一)数组解构赋值

    (1)一般从后端的API获取到的JSON中就会存在数组,如何快速接收这些数组的值,这时候用解构赋值的方式最好不过了;

    (2)利用数组的解构赋值,快速将两个变量的值互换;
    额外说一点的是 let声明的变量不可以重复声明(一旦重复声明就会报错),但是这个变量可以被覆盖,const声明的变量一经声明就必须赋值且不可以被修改(这个知识点放这里可能有点突兀,而且不是重点,但是脑子里面突然想到了,就写下来,哈哈)
    (3)数组的解构赋值与扩展运算符 … 的结合,可以接收剩余参数,这些剩余参数将以数组的形式接收储存并返回
    (3-1)在解构过程中,如果我们不需要某个变量,可以直接用一个逗号去进行忽略;
    (3-2)如果对于一个数组,我们只想要数组中的前几个值,对于剩下的值,虽然我现在不需要,但是我还想先储存下来,这时候我们就可以使用扩展运算符紧跟一个变量的形式如 …a (扩展运算符一定的放在最后面的,否则会报错的)将剩下的数据用一个变量a进行接收(详见上图),返回的a是一个数组,如果没有接收到,就会返回空数组

(二)对象解构赋值

    (1)对象的解构赋值我们要求用来接收数据的变量一定要和这个数据的属性名一致,否则获取不到数据;
let {id,rating}=json;是let {id:id,rating:rating}=json;的简写

    (2)如果我们用来接收数据的变量和这个数据的属性名不一致,必须写成这样:let {author:name,title:txt}={author:’Tony’,title:’理发店’};才能取到相应的数据值(如下图所示)

    (3)对象的解构赋值可以用于嵌套的对象,但是一定要注意模式的匹配(解构赋值就是‘模式匹配’)(如下图所示)

    (3-1)这里可以注意一下逗号的使用,在数组中如果我们要忽略某一项的数据的话,可以用一个逗号去实现,忽略几个就在前面写几个逗号(因为数组中的数据都是按照一定的次序来的,所以这样操作才能保证我们想要的数据能正确取到)
    (3-2)对于这种嵌套的对象,在以往我们要去循环才能把我们想要的数据获取到,但是现在通过解构赋值的方式很轻松的获取到我们想要的数据
    (3-3)对象的解构赋值,虽然要求变量要和属性名一致(最好一样,不一样的话模式也要一样),但是对于顺序不做要求,这就意味着我们可以不在意对象里面属性的顺序,只在乎我们需要的属性名就好了
    (4)这里特别说明的一点就是对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

    像这个图片里面的代码一样author:name,title:txt ,author是模式名(不会被声明的),name才是接收数据的变量,真正被赋值的是变量name,而不是模式author,这个一定要区分开来。

(三)函数参数解构赋值

    (1)ES6中,函数的参数也支持解构赋值。这对于有复杂配置参数的函数十分有用。我们可以结合使用数组和对象的解构赋值。

    (2)函数的参数的解构赋值中,可以设置参数的默认值,但是以下两个默认值的设置方式看似相同,其实不然,其中有一种设置的方法是不恰当的。需要加以区分辨别
    (2-1)第一种(其实只是为函数整个形参设置了默认值,而不是解构赋值过程中的变量设置了默认值):

    (2-1-1)这里提别说明一下:{publisher,price}这里不是对象,这是解构赋值为了接收传进来的对象里面的属性值value值,{publisher,price}这个整体是这个函数的形参,所以{publisher,price}={publisher:0,price:0}就是给函数的形参设置默认值的,当函数在调用的时候,没有传入参数的时候,这时候默认值就其作用了。所以我们在对函数形参进行解构赋值的时候,这种设置默认值的方式是不正确的,因为它不是为解构赋值设置的默认值
    (2-1-2)我们看到当我们为上图的_demotest()函数传入一个空对象的时候,得到的结果是两个undefined而不是默认值。这里涉及到的知识点有两个:①函数或者解构赋值设置默认值的时候,默认值生效的前提就是这个变量 === 全等于undefined的时候,才会触发默认值 ② {}空对象在栈内存中也是存在一个确切的引用地址的,所以不会触发默认值生效的条件
上图代码:_demotest({});//undefined undefined
    (2-2)第二种(这才是函数形参解构赋值过程中的变量设置了默认值):

    这里说明的是:{a=0,b=0}这才是函数形参解构赋值过程中的变量设置了默认值
    (3)函数的解构赋值过程中,还可以使用rest参数(…),通过rest参数,我们可以实现以下功能:
    一、我们可以用解构赋值接收函数返回的所有的数据(储存在一个数组中);

    二、使用rest参数,可以将所有传入函数的形参以数组的形式传递进函数作用域内,值的注意的是:这里的数组是真的数组实例,而不是arguments一样的类数组

(四)字符串解构赋值

    (1)字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象(敲黑板划重点)这个类似数组的对象中的元素是由这个字符串的每一个字符组成的

    (2)字符串的解构赋值相对而言比较简单并没有什么特别之处。

(五)布尔值和数值的解构赋值

    (1)这两种数据类型一般用解构赋值的场景比较少(因为它数据值简单、单一),写在一起是因为他们的规则都是一样的。
    (2)布尔值和数值解构赋值的规则是,如果等号右边的是布尔值和数值时,就先将其转化为对象。转换的是原生对象(Boolean和Number)的toString方法

    (3)这里再提一下,由于undefined和null无法转换为对象,所以使用undefined和null进行解构赋值的话,就会报错。

3_解构赋值的使用注意事项

    (一)解构赋值一般用于数组或对象。其他原始类型的值都可以转为相应的对象。但是undefined和null无法转换为对象,如果对undefined或null进行解构,会报错。

    // 以下代码会报错
    let [foo] = undefined;
    let [foo] = null;

    (二)在指定默认值时,赋值为nullundefined是不同的,ES6内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。

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


    上面代码中,因为x能取到值,所以函数 f 根本不会执行

    (四)注意默认值的顺序


    上面是因为x用到默认值y时,y还没有声明。let/const不允许变量在未声明的情况下使用,上面的代码如果把let改为var则不会返回x=undefined

    (五)数组的解构赋值:数组的元素是按次序排列的,变量的取值由它的位置决定

    (六)对象的解构赋值:属性没有次序,变量必须与属性同名,才能取到正确的值。

    (七)如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。

    (八)对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。

    (九)在函数参数中使用解构赋值注意区别函数的参数的默认值和变量默认值的区别

    (十)圆括号的使用问题

    解构赋值虽然很方便,但是解析起来并不容易。对于编译器来说,一个式子到底是模式,还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能知道。

    由此带来的问题是,如果模式中出现圆括号怎么处理。ES6的规则是,只要有可能导致解构的歧义,就不得使用圆括号。

    但是,这条规则实际上不那么容易辨别,处理起来相当麻烦。因此,建议只要有可能,就不要在模式中放置圆括号。
    不能使用圆括号的情况
    (一)以下三种解构赋值不得使用圆括号。
    (10-1)变量声明语句中,不能带有圆括号。

    (10-2)函数参数中,模式不能带有圆括号。

    (10-3)不能将整个模式,或嵌套模式中的一层,放在圆括号之中。

    (二)可以使用圆括号的情况
    (10-4)可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。

4_小结

    解构赋值的主要用途:
    1.交换变量的值
    2.从函数返回多个值
    3.函数参数的定义
    4.提取JSON数据
    5.函数参数的默认值
    6.遍历Set Map结构
    7.输入模块的指定方法
    还有很多。。。

5_参考文档

    https://www.jianshu.com/p/0b2d59c21188
    https://www.jianshu.com/p/8fe6ed15b30d
     https://wohugb.gitbooks.io/ecmascript-6/content/docs/destructuring.html
    https://blog.csdn.net/palmer_kai/article/details/78464530