ES6标准学习: 2、解构赋值

解构赋值

 

1、基本使用方法

es6允许按照一定的方式,从数组和对象中提取值,从而对变量进行赋值,这种模式被称为解构。

以前,我们为一个变量赋值,通常这么写:

1 var a = 1
2 var b = 2
3 var c = 3 

而在es6中,我们可以这么写:

1 var [a, b, c] = [1, 2 , 3] 

上面的代码表示,我们可以从数组中提取值,并按照位置的对应关系对变量进行赋值。

嵌套的解构赋值也是允许的:

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

某些位置没有需要被赋值的变量也是允许的:

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

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

1 var [value] = []
2 var [a, b] = [1]
3 
4 // value,b 都是undefined

还有一种情况是不完全解构,即等号左边的模式值等于等号右边的模式的一部分,这中情况下,解构也是可以成功的:

1 let [x, y] = [1, 2, 3]
2 // x = 1
3 // y = 2

注意:如果等号右边的不是可以遍历的结构,那么将会报错

// 报错
let [vaule] = 1
let [vaule] = false
let [vaule] = NaN
let [vaule] = undefined
let [vaule] = null
let [vaule] = {}

 

2、默认值

解构赋值允许制定默认值

1 var [value = true] = []  // value = true
2 var [x, y = 'b']  = ['a'] // x= 'a' y ='b'
3 var [x, y = 'b']  = ['a', undefined]  // x = 'a' y = 'b'

这里解释一下最后一行,es6内部使用 === 判断一个位置是否优质,所以,如果一个可遍历解结构的成员不严格等于undefined,默认值是不会生效的:

1 var [x = 1] = [undefined] // x = 1
2 var [x = 1] = [null]  // x = null

因为null不严格等于undefined,所以第二行的x = null

默认值可以引用解构赋值的其他变量,但该变量必须已经声明

1 let [x = 1, y = x] = [] // x = 1, y = 1
2 
3 let [x = 1, y = x] = [2] // x = 2, y = 2
4 
5 let [x = 1, y = x] = [1, 2] // x = 1, y = 2
6 
7 let [x = y, y = 1] = []  // ReferenceError

 

3、对象的解构赋值

解构不仅可以用于数组,还可以用于对象

1 var {a, b} = {a: 1, b: 2}
2 // a: 1
3 // b : 2

对象解构与数组的解构有一个很大的区别在于:数组的元素是有顺序的,变量的取值由它的位置所决定,而对象的属性没有次序,变量必须与对象的属性同名,才能被正确的赋值:

1 var {c} = {a: 1, b: 2}
2 // c: undefined

如果真的需要变量名与属性名不一致,那么必须像下面这样写:

1 var {a: value} = {a: 1}
2 // value  = 1 
3 
4 let obj = {first: 1, last: 2}
5 let {f: first, l: last} = obj
6 // f : 1
7 // l : 2

从以上的代码中,我们其实可以看出来,对象的解构赋值,其实是下面这种形式的缩写:

var {first: first, last: last} = {first: 1, last: 2}

也就是说,对象的解构赋值,是先找到同名的属性,然后在赋值给对应的变量,真正被赋值的是后者,而不是前者。

采用这种写法时,变量的声明和赋值是一体。对于let和consteryan ,变量不能重新生命,所以一旦赋值的变量以前声明过,就会报错:

1 let first
2 let {first} = {first: 1} // SyntaxError: Duplicate declaration 'first'

和数组一样,解构也可以用于嵌套结构的对象

 1 var obj = {
 2   p: [
 3     'hello',
 4     {y: 'helloy'}
 5   ]
 6 }
 7 
 8 var { p: [x, {y}] } = obj
 9 // x = 'hello'
10 // y = 'helloy'

对象的解构也可以指定默认值,默认生效的条件是:对象的属性值严格等于undefined。并且如果解构失败,那么变量的值就等于undefined

注意:如果解构模式是嵌套的对象,而且子对象所在的福属性不存在,会报错:

1 var {foo: {bar}} = {baz: 'baz'}

在上面的代码中,等号左边对象的foo属性对应于一个子对象。该子对象的bar属性解构时会报错。因为foo这时等于undefined,再取自子属性就报错

如果讲一个已经声明的变量用于解构赋值,需要注意写法:

// 错误的写法
var x 
{x}  = {x: 1} // SyntaxError: syntax error

为什么上面代码会报错?

因为js的引擎会将{x}理解成一个代码块,从而发生了语法错误。 只有不将大括号写在行首,才能避免js引擎将其解释为代码块。

// 正确的写法
({x} = {x: 1})

 

4、字符串、数值和布尔值的解构赋值

1、字符串也可以解构赋值,此时字符串被转换成了一个类似数组的对象

const [a, b, c, d, e] = 'hello'
// a: h
// b: e
// c: l
// d: l
// e: o

2、解构赋值时,如果等号右边的时数值或者布尔值,则会先转换为对象

1 let {toString: s} = 123
2 s === Number.prototype.toString // true

 


5、函数参数的解构赋值

1、基本使用

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

在上面的代码中,函数add的参数其实并不是一个数组,而是通过解构得到的变量x, y

2、函数参数解构的默认值

函数参数的解构也可以使用默认值:

1 function move ({x = 0, y = 0} = {}) {
2   return [x, y]
3 }
4 
5 move({x: 1, y: 1}) // [1, 1]
6 move({x: 3}) // [3, 0]
7 move({}) // [0, 0]
8 move() // [0 ,0]

在上面的代码中,函数move的参数是一个对象,通过对这个对象的解构赋值,得到变量x与y的值,如果解构失败,x, y为默认值

这里还有另一种写法,可以与上面的写法比较一下,看看有什么不同:

1 function move({x, y} = {x: 0, y: 0}) {
2   return [x, y]
3 }
4 
5 move({x: 1, y: 1}) // [1, 1]
6 move({x: 1})  // [1, 0]
7 move({}) // [undefined, undefined]
8 move() // [0, 0]

这种写法,其实是为函数move的参数指定默认值,而不是为x ,y 变量指定默认值,所以两种写法的结果并不相同。

 

6、用途

解构赋值有哪些用途呢?

1、交换变量的值

[x, y] = [y, x]

2、从函数返回多个值

1 function example() {
2   return [1 ,2, 3]
3 }
4 var [a, b, c] = example()

3、函数参数的定义

 1 function fn([x, y, z]) {
 2   //...
 3 }
 4 fn([1, 2, 3])
 5 
 6 
 7 function fn({x, y, z}) {
 8   //...
 9 }
10 fn({z: 3, x: 1, y: 2})

4、提取json数据

1 var json = {
2   'id': '42',
3   'status': 'ok',
4   'data': [1, 2]
5 }
6 let {id, status, data} = json

5、指定函数参数的默认值

 

以上就是对解构赋值的大概介绍,如果有什么问题,还请读者指出批评。

 

参考书籍: 《ES6标准入门--阮一峰》

posted @ 2017-04-23 15:41  吞佛童子  阅读(132)  评论(0编辑  收藏  举报