数组的解构赋值
PS:解构赋值的规则是,只要等号右边的值不是对象或数组,就先其转换为对象,需要注意的是undefined和null无法转换成对象,在使用它们时会出错。
以前我们声明变量,只能指定值。
var a = 1;
var b = 2;
var c = 3;
而现在Es6出现变量解构赋值,看下面写法
var [a,b,c] = [1,2,3]
console.log(a,b,c) // 1 2 3
这样的赋值只能对应的位置,对应的值。
这种写法属于 "模式匹配" 只要等号两边的模式相同,左边的变量就会被赋予对应的值 , 下面展示一下嵌套结构。
var [name,[abc],age] = ['秦司令',[123],20]
console.log(name,abc,age) // 秦司令 123 20
var [,,baz] = ['秦司令',20,'baz']
console.log(baz) // 'baz'
上面代码中, 写成逗号其实是占位的。
如果解构不成功,默认是undefined。
var [foo] = []
var [x,y] = [1]
上面的代码中,变量foo和变量y都是undefined
如果等号的右边不是数组或者不是一个可遍历的结构,那么就会报错。
var [foo] = null;
var [foo] = undefined;
var [foo] = false;
var [foo] = true;
var [foo] = NaN;
var [foo] = {};
var [foo] = 10
上面的几种写都会报错,因为它们都不能遍历。
对于Set结构,也可以使用解构赋值,因为Set结构具有可遍历Iterator接口。
var [x,y,z] = new Set(['a','b','c'])
console.log(x,y,z) // a b c
默认值
数组的解构赋值允许指定默认值。
let [qin = 1] = []
console.log(qin) // 1
let [name1,y = 'b'] = ['秦司令'];
console.log(name1,y) // 秦司令 b
let [name2,y1 = 'b'] = ['秦司令',undefined]
console.log(name2 , y1) // 秦司令 b
let [name3,y2 = 'y2'] = ['秦司令',null]
console.log(name3,y2) // 秦司令 null
上面代码中,Es6内容使用的是严格相等运算符(===),判断一个位置的值是否存在,因此undefined会被认为是一个空值,如果是一个null值的话,那么默认值就不会生效,因为undefined不严格等于null。
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] = [] // 报错
上面代码中,最后一个语法报错的原因是因为,x = y的时候 y还没有被声明,所以会报错。
对象的解构赋值
解构赋值不仅能用于数组,还能用于对象。
let {name,age} = {name:'秦司令',age:19}
console.log(name) //秦司令
console.log(age) // 19
对象的解构与数组不同的是,数组解构是按位置次序的,但是对象的解构是变量值对应属性值,不论什么位置。
let {bar,foo} = {foo:'abc',bar:123};
console.log(bar) //123
console.log(foo) // 'abc'
let {sex} = {foo:'abc',bar:123}
console.log(sex) // undefined
上面代码中,第一个列子是对应的变量取对应的属性,并没有按照顺序赋值,第二个列子,变量没有对应的属性,取不到值成了undefined。
如果变量名与属性名不一致,必须写成这样。
let {name:q} = {name:'秦司令',age:19}
console.log(q) // 秦司令
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量,真真被赋值的是后者,而不是前者。
let {name:q1} = {name:'秦司令',age:19}
console.log(q1) // 秦司令
console.log(name) // 空值
上面代码中,name是匹配模式,q1才是变量,真正被赋值的是q1,而不是模式name。
对象解构赋值与数组一样,对象也可以解构嵌套对象。
var json = {
p:[
'秦司令',
{age:20}
]
}
let {p:[_name,{age:n}]} = json
console.log(_name,n) // '秦司令' 20
上面代码中,p是一个模式,不能当做一个变量,如果想当做变量,这样写。
var json = {
p:[
'秦司令',
{age:20}
]
}
let {p,p:[_name,{age:n}]} = json
console.log(p,_name,n)
这样p就当做一个变量处理了。
嵌套赋值
var _obj = {};
var _arr = [];
({name:_obj.name,age:_arr[0]} = {name:'秦司令',age:19})
console.log(_obj,_arr) // {name:'秦司令'} [19]
上面代码中,赋值圆括号() 里面写解构
对象的解构也可以指定默认值。
var {x = 3} = {}
console.log(x) // 3
var {x,y = 3} = {1}
console.log(x,y) // 1 3
var {x:y = 3} = {}
console.log(y) // 3
默认值生效的条件是,属性值必须是undefined
var {name = '秦司令'} = {undefined}
console.log(name) // 秦司令
var {sex} = {null}
console.log(sex) // null
上面代码中,undefined与null严格不相等,所以null是一个有效的值,不能称为 "空值" undefined。
如果对象解构失败,则变量值是undefined
let {foo} = {bar:'123'}
console.log(foo) // undefined
如果将一个已经声明的变量用作解构赋值,得注意点。
let x;
{x} = {x:1} //报错
上面代码中,报错的原因是因为,刚声明的一个变量,js引擎会将{x}理解成一个代码块,然后会直接报错,写上圆括号就能解决此问题。
let x;
({x} = {x:1}) // 1
字符串的解构赋值
字符串也可以赋值,这是因为此时,字符串被转换成了一个类似于数组的对象。
let [a,b,c,d,e] = 'hello'
console.log(a,b,c,d,e) // h e l l o
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
let {length} = 'hello'
console.log(length) // 5
用解构赋值写一个变量交换值,非常简单
let x = 1
let y = 2
[x,y] = [y,x]
// x 2
// y 1
数值和布尔值的解构赋值
在解构赋值是,只要等号右边的值不是对象或数组,就先将其转为对象。
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
上面代码中,数值和布尔值的包装类对象都有toString属性,因此变量s都能取到值。