ES6学习笔记2 变量的解构赋值
ES6学习笔记2 变量的解构赋值
基本用法
ES6允许按照一定模式从数组和对象中提取值,然后对变量进行赋值
let [a,b,c] = [1,2,3];
a //1
b //2
c //3
let [a, [[b], c]] = [1, [[2], 3]];
a //1
b //2
c //3
let [x, ,y] = [1,2,3];
x //1
y //3
如果对应变量解构不成功,则该变量的值将会为undefined
let [x,y] = [1];
x //1
y //undefined
如果=的右边不是可迭代的结构,就会报错。事实上,只要某种数据结构具有Iterator接口,就可以采用数组形式的解构赋值,例如Set结构,Generator函数
let [foo] = 1; //报错
let [foo] = true; //报错
let [foo] = null; //报错
let [foo] = undefined; //报错
let [x,y,z] = new Set([‘a’,’b’,’c’]);
x //’a’
function* fibs(){
let a = 0;
let b = 1;
while(true){
yield a;
[a,b] = [b,a+b]
}
}
let [first,second,third,fourth,fifth,sixth] = fibs();
sixth //5
默认值
解构赋值允许指定默认值,若对应的变量解构后值为undefined,则将采用默认值,,否则默认值不生效
let [x=1] = [];
x //1
let [x,y=2] = [1];
x //1
y //2
如果默认值是一个表达式,则这个表达式是惰性求值的,即只有将其作为默认值赋值时才会求值
function f(){
return 2;
}
let [x = f()] = [1];
上述代码中,因为x能取到值,因此函数f不会执行
默认值可以引用其他变量,但该变量必须已经声明
let [x=1, y=x] = [2] //x=2,y=2
let [x=y, y=1] = [] //报错,因为y未声明就被先使用
对象的解构赋值
对象的解构与数组有一个重要不同,对象的属性没有次序,变量必须与属性名同名才能取到正确的值
let { foo, bar} = {foo:’aaa’, bar:’bbb’};
foo //’aaa’
bar //’bbb’
如果变量名与属性名不一致,必须写成如下格式
let {foo:baz} = {foo:’aaa’, bar:’bbb’};
baz //’aaa’
实际上,对象的解构赋值是下面形式的简写
let { foo:foo, bar:bar} = {foo:’aaa’, bar:’bbb’};
1
这表示对象的解构赋值的内部机制是先找到同名属性,然后再赋值给对应的变量。真正被赋值的是后者,而不是前者
let {foo:baz} = {foo:’aaa’, bar:’bbb’};
baz //’aaa’
foo //报错,foo未定义
与数组一样,解构也可以用于嵌套结构的对象
let obj = {
p: [
‘hello’,
{y:’world’}
]
};
let { p:[x, {y}] } = obj;
x //’hello’
y //’world’
对象的解构也可以指定默认值,默认值生效的条件与数组类似
var {x, y=5} = {x:1};
x //1
y //5
var {x:y=3} = {x:5};
y //5
如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,将会报错,原因在于此时将对undefined取子属性
let {foo:{bar}} = {baz:’baz’}; //报错
如果要将一个已经声明的变量,用于解构赋值,应该小心
let x;
{x} = {x:1}; //报错
上述javascript会将{x}理解为一个代码块,只有不将大括号写在行首,才能避免此问题
let x;
({x} = {x:1}); //x=1
常见应用
获取Math对象的方法
let {log, sin, cos} = Math;
获取数组项
let arr = [1,2,3];
let {0:first, [arr.length – 1]:last} = arr;
first //1
last //3
字符串的解构赋值
字符串被转换为一个类似于数组的对象
const [a,b,c] = ‘xyz’;
a //’x’
b //’y’
c //’z’
let {length:len} = ‘xyz’;
len //3
数值和布尔值的解构赋值
如果等号右边是数值和布尔值,则会先转化为对象,再赋值
let {toString:s} = 123;
s //’123′
let {toString:s} = true;
s //’true’
此处数值和布尔值包装对象都有toString属性,因此他们都能取到值
函数参数的解构赋值
参数传入那一刻,自动被解构赋值
function add([x,y]){
return x+y;
}
add([1,2]); //3
可以使用默认值
function add([x=0,y=0]){
return x+y;
}
add([]); //0
add([1]); //1
add([1,1]); //2
圆括号问题
以下情况不能使用圆括号:
变量声明语句
let [(a)] = [1]; //报错
1
函数参数
function f([(z)]){
return z;
} //报错
赋值语句的模式
([a]) = [5]; //报错
({p:a}) = {p:1}; //报错
圆括号只能使用在赋值语句的非模式部分
[(b)] = [3]; //正确
({p:(d)} = {}); //正确
上述*行语句,模式是取数组*个成员,与圆括号无关。第二个语句,模式是p,与圆括号无关。
用途
从函数返回多个值
function example(){
return [1,2,3];
}
let [a,b,c] = example();
函数参数的定义
function f([x,y,z]){ … }
f([1,2,3]);
提取JSON数据
let jsonData = {
id:42,
status:’ok’,
data:[1,2,3]
}
let {id,status,data} = jsonData;
函数默认参数值、遍历Map结构、输入模块指定方法等