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标准入门--阮一峰》