1.数组的解构赋值


基本用法

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

在ES6之前想要为变量赋值,只能指定其值,如下:

let a = 1;
let b = 2

而在ES6中可以写成这样,如下:

let [a,b] = [1,2]
// a = 1, b = 2

值得注意的是,等式两边的值要对等,这样左边的变量才会被赋上右边对应的值,如果不对等左边的值将会出现undefined,如下写法:

let [foo,[[bar],baz]] = [1,[[2],3]]
foo // 1
bar // 2
baz // 3

注意:只有左右两边的 格式一定要对等,数量可以不对等。

let [a,b,c] = [1,2]
a = 1, b = 2, c = undefined

let [a,,c] = [1,2,3]
a = 1, c = 3

let [a, ...b] = [1,2,3]
a = 1, b = [2,3]

let [a] = []
let [b,a] = [1]
a = undefined

还有一种情况,等号左边为数组,但是等号右边为其他值,将会报错。如下:

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

以上都会报错

但是如果左边为数组,右边为字符串,将会取字符串的第一个下标的值

let [a] = '121321'  a = '1'
let [a] = 'adgasg'  a = 'a'

对于Set结构,同样可以使用数组的解构赋值。

let [x,y,z] = new Set([1,2,3])
x = 1, y = 2, z = 3

默认值

解构赋值允许指定默认值

let [a = 3] = []        // a:3
let [a = 3,b] = [,4]    // a:3 b:4
let [a = 3,b] = [5,4]   // a:5 b:4

特殊

let [a = 3] = [undefined]   // a:3
let [a = 3] = [null]        // a:null

++++==Tips==++: 在es6中使用严格相等运算符,在结构赋值中如果需要默认值生效,则应对等的值为undefined的时候才会采用默认值,否则还是使用赋值。上面中null 不严格等于undefined++

如果默认值的赋值为一个表达式,只有当等号右边的赋值没有值为undefined的时候,才会取表达式中的值,如下:

function demo(){
    console.log('demo')
}

let [a = demo()] = []   // a: demo
let [a = demo()] = [1]  // a : 1

对象的解构赋值


与数组的不同点是,数组的元素必须和赋值的元素要位置一致才能正确的赋值,而对象的解构赋值则是等号两边的变量和属性同名即可取到正确的值。否则值为 undefined

let {a,b} = {a:'23',b:'3'}
let {a,b} = {b:'3',a:'23'}

// 上面两个的值 都是 a: 23 b: 3

let {a,b} = {a:'3',c:'d'}
//a: 3 b: undefined

对象的解构赋值还有将某一个现有对象的方法赋值到一个新的变量,如下:

let {sin,cos} = Math
// Math 中的sin cos 方法将赋值给变量 sin cos

let {log} = console
// log(2)  ===  console.log(2)

如果等号左边的变量名不能和等号右边的对象的属性名一致,则必须写成如下格式:

let {a:b} = {a:'ss'}     // b:ss
//a是属性名,b才是实际赋值的变量名

对象的解构赋值一样是可以嵌套解构的,如下:

第一种:

let obj = {
    p:[
        'Hello',
        {y:'world'}
    ]
}

let {p:[x,{y}]} = obj 
// x: Hello, y: world

这边的p只是属性不是变量,如果p想赋值可以写成:

let {p,:[x,{y}]} = obj

第二种:
const a = {
    loc: {
        t :1,
        b :{
            c:1,
            d:2    
        }
    }
}
let {loc:{t,b:{c,d}}} = a
或者
let {loc,loc:{t,b,b:{c,d}}} = a
嵌套赋值
let o = {}, arr = []

({foo:o.prop,bar: arr[0]} = {foo:123,bar:true})
//o: 123, arr = [true]

如果解构模式 是嵌套的对象,如果子对象所在的父属性不存在,则会报错,如下:

let {foo:{bar}} = {baz:'baz'} //报错

默认值

let {x = 3} = {}
// x: 3

let {x,y = 5} = {x : 1}
// x: 1, y: 5

let {x: y = 5} = {}
// y = 5

let {x: y = 5} = {x : 4}
// y = 4

let {x: y = 'hhhh'} = {}
//y = 'hhhh'

Tips:以上左边 x为属性名,y为变量


let {x = 5} = {x: undefined}
// x: 5

let {x = 4} = {x: null}
// x: null

同数组一样遵循 严格等于 
只有右边为undefined的时候默认值才会生效
注意点:

1)不能将已声明的变量用于解构赋值,因为已经是一个代码块。

字符串的解构赋值

如果赋值的对象是数组,字符串将被分割为数组的格式,一一对应赋值

let [a,b] = 'ha'
// a = h , b = a

同时可以获得字符串的长度:

let {length:len} = '12121'
// len = 5

数值和布尔值的解构赋值

如果等号右边是数字或者布尔值 则转换成对象或者说,除了是数组和对象,其他值都将转换成对象,null 和 undefined 除外。如下:

let {t:s} = 123
let {t: s} = true

函数参数的解构赋值

function add([x,y]){
    return x+y
}
add([3,5]) // 8

[[3,5],[6,7]].map(([a,b]) => a + b)
//8 , 13

function m({x=3, y=4} = {}){
    return [x,y]
}
m({x:33,y:8})     // [33,8]
m({x:32})         // [32,4]
m({})             // [3,4]
m()               // [3,4]

function m({x,y} = {x=0,y=0}){
    return [x,y]
}
m({x:33,y:8})     // [33,8]
// 代替右边的 x:0, y:0 所以是传值 33  8

m({x:32})         // [32,undefined]
//因为传值替代右边的赋值,但是只有x没有y
//所以y是取   左边y的默认值,因为你没有赋值 为undefined

m({})             // [undefined,undefined] 
// 取左边x,y的默认值,因为没有赋值 为undefined

m()               // [0,0]
// 没有传值,使用本身的赋值 都是0

其他

不能使用圆括号的情况

  1. 变量声明语句
  2. 函数参数
  3. 赋值语句的模式

可以使用圆括号的情况

  1. 赋值语句的非模式部分,可以使用圆括号

解构赋值的用途

  1. 交换变量的值
  2. 从函数返回多个值
  3. 函数参数的定义
  4. 提取JOSN数据
  5. 函数参数的默认值
  6. 遍历Map解构
  7. 输入模块的指定方法