第二章:解构赋值

拾穗者

变量的解构赋值

基本用法

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构函数

1
2
3
4
let [a,b,c]=[1,2,3];
//a=1
//b=2
//c=3

上面的代码表示,可以从数组中提取值,按照位置的对应关系对变量赋值,本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

嵌套结构赋值

结构赋值也可以进行嵌套,只要左右两边能够找到相互对应的值,就可以了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let [foo,[[bar],baz]] = [1,[[2],3]]
//foo=1
//bar=2
//baz=3
let [ , ,third] = ['foo','bar','baz']
//third='baz'
let [head,...tail] = [1,2,3,4,5]
//head=1
//tail=[2,3,4,5]
let [x,y,...z] = ['a']
//x='a'
//y=undefined
//z=[]

解构赋值规则

  • 如果解构不成功,变量的值就等于 undefined

    1
    2
    3
    4
    var [foo]=[]//foo=undefined
    var [bar,foo]=[1]
    //bar=1
    //foo=undefined
  • 当出现不完全解构时,即等号左边的模式只匹配等号右边数组的一部分,这种情况下,解构依然可以成功

    1
    2
    3
    4
    5
    6
    7
    8
    let [x,y] = [1,2,3]
    //x=1
    //y=2
    let [a,[b],c]=[1,[2,3],4]
    //a=1
    //b=2
    //c=3
  • 如果等号的右边不是数组(或者不可遍历对象),那么将会报错

    1
    2
    3
    4
    5
    6
    let [foo] = 1
    //报错
    let [foo] = false
    //报错
    let [foo] ={}
    //报错
  • 解构赋值不仅适用于var命令,也适用于let和const命令

  • 对于Set结构,也可以使用数组的解构赋值
    什么是Set结构?
    说起Set结构,就要提到Iterator的概念。
    Iterator(遍历器)就是一种需要统一的接口机制来处理所有不同的数据结构,他是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署Iterator接口,就可以完成便利操作(即依次处理该数据结构的所有成员)
    Set结构原生具有Iterator接口,可以直接使用for..of循环

    1
    2
    3
    4
    5
    6
    7
    8
    var engines = new Set([1,2,3,4,4])
    for(var e of engines){
    console.log(e)
    }
    //1
    //2
    //3
    //4

    上面的代码就是遍历了Set结构的方法,由此可见,Set结构也可以进行去重
    使用Set结构遍历时返回的是一个值

  • 事实上,只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function* fibs(){
    var a = 0
    var b = 1
    while(true){
    yield a;
    [a,b] = [b,a+b]
    }
    }
    var [a,b,c,d,e,f] = fibs()
    //f=5

    fibs是一个Generator函数,什么是Generator函数呢?
    此知识点仅为了解,以后会具体解释Generator的意义:Generator是ES6提供的一种异步编程解决方案,从语法上,可以理解成一个状态机,封装了很多内不状态,执行Generator函数会返回一个遍历器对象,现在我们只要了解这个函数可以遍历即可

默认值

  • 结构赋值允许指定默认值

    1
    2
    3
    4
    5
    6
    var [foo=true] = []
    //foo = true
    var [x,y=b] = ['a']
    //x='a'
    //y='b'
  • ES6内部使用严格相等运算符(===)来判断一个位置是否有值,,所以如果数组成员不严格等于undefi的话,默认值是不会生效的

    1
    2
    3
    4
    var [x=1] =[undefined]
    //x=1
    var [x=1] = [null]
    //x=null(由于null和undefined在严格模式下是不相等的,所以默认值并没有生效)
  • 如果默认值是一个表达式,那么这个表达式是惰性求值得,即只有再用到的时候才会求职

    1
    2
    3
    4
    5
    function f(){
    console.log('aaa')
    }
    let [x=f()]=[1]
    //1

    由于x能取到值,所以函数f根本不会执行,所以代码可以等价于下面代码

    1
    2
    3
    4
    5
    6
    let x;
    if([1][0]===undefined)//判断结构右边的值是否等于undefined
    x = f() //是的话,就将x赋值为默认值
    }else{
    x = [1][0]//不是的话,就将x赋值为等号右边的值
    }
  • 默认值可以引用解构函数赋值的其他变量,但该变量必须已经声明

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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

    最后一个表达式之所以会报错,是因为x用到默认值y是还没有声明