变量的解构赋值
1.数组解构赋值
1.1 基本用法
ES6允许按照一定模式,提取数组或对象的值,对变量赋值,称之为解构赋值
以往对变量赋值如下:
var a=10; var b=20; var c=30;
ES6中可写成以下形式:
var [a,b,c] = [10,20,30];
这种写法属于“模式匹配”,只要等号两边的模式对应,右边的值便会赋予左边对应的变量。
注意下面的写法:
// ... 是扩展运算符,代表剩余所有参数
var [a, ...b] = [1,2,3,4]; a //1 b // [2,3,4]
var [a, , b]=[1,2,3] a //1 b //3
//解构赋值可以嵌套 var [a,[b,c],d]=[1,[2,3],4] a //1 b //2 c //3 d //4 //如果解构不成功,变量值为undefined var [a,b,...c] = [1] a //1 b //undefined c //[]
注意,只要某种数据结构具有Iterator接口,就可以采用数组形式的解构赋值,结构赋值也适用于let,const命令
1.2 默认值
解构赋值可以指定默认值
let [a=2]=[] a //2 let [x,y=3]=[4] x //4 y //3
ES6内部用===判断一个位置是否有值,所以一个成员变量不严格等于undefined,默认值不生效
var [a=10] = [undefined] a //10 var [b=20] = [null] b//null
如果默认值是一个表达式,只有需要用到表达式时候才会求值
function foo(){ console.log('I love u') } let [x=foo()]=[666] x //666
默认值可以是变量,但此变量必须已经声明
let [a=2,b=a] = [] a //2 b //2 let [a=b,b=1] = [] //Reference Error
2.对象解构赋值
2.1 基本用法
对象的属性没有次序,变量名必须与属性同名,才能取到正确的值
var {bar,foo} = {foo:"abc", bar:"def"}; foo // "abc" bar // "def"
如果变量名和属性名不相同,必须写出以下形式
var {foo:p} = {foo:"abc" , bar:"def"} p // "abc"
这说明了对象的解构赋值其实是以下形式的简写
var {bar:bar,foo:foo} = {foo:"abc", bar:"def"};
对象解构赋值的内部机制,实现找到对应同名属性,在赋值给对应的变量,真正被赋值的是冒号后面的变量,而不是冒号前面的属性
与数组相同,解构赋值也可用于嵌套结构的对象
var obj={p:["abc" , {y:12}]} var {p:[x,{y}]} = obj x // "abc" y // "12"
以上代码中,p是模式不是变量,不会被赋值
2.2 默认值
对象的解构赋值也可以指定默认值,默认值生效条件是,对象属性严格等于undefined
var {a:1} = {a : undefined}; a // 1 var {b:1} = {b : null}; b // null
2.3 注意事项
1.将一个已经声明的变量用于解构赋值
var a; {a} = {a=1};
上面代码会报语法错误,因为js引擎会把{a}理解成代码块。只有不把大括号写在行首,才能避免这样的错误,比如用()括起来
({a} = {a=1})
2.结构赋值允许等号左边的模式中不放任何变量名
{} = {1,2,3}
虽然上面的代码毫无意义,但是不报错
3.对象的解构赋值可以很方便的把现有对象的属性方法赋值给某个变量
let {floor , ceil , abs} = Math
3.字符串解构赋值
字符串在解构赋值时 被转为类数组对象,可以对其length属性解构赋值
let {a,b,c,d,e,length:len} = "hello" a // "h" b // "e" c // "l" d // "l" e // "o" len // 5
4.数值和布尔值解构赋值
解构赋值是,若等号右边是数值或布尔值,则会先转为对象
let {toString:s} = 666 s === Number.prototype.toString // true let {toString:s} = true s === Boolean.prototype.toString // true
5.函数参数解构赋值
function sum([x,y]){ return x+y; } sum([1,2]) // 3
函数参数结构赋值也可以指定默认值,但要注意
function foo({x=0,y=0} = {}){ return [x,y]; }
foo({x:1,y:2}) // [1,2]
foo({x:1}) // [1,0]
foo({}) // [0,0]
foo() // [0,0]
function bar({x,y} = {x:0,y:0}){ return [x,y]; }
bar({x:1,y:2}) // [1,2]
bar({x:1}) // [3,undefined]
bar({}) // [undefined,undefined]
bar() // [0,0]
foo函数参数是一个对象,对象中指定了x,y的默认值,通过对这个对象解构赋值,得到x和y的值;bar函数是为函数的参数整体指定默认值,不是为x,y指定默认值,x,y没有默认值!