解构赋值
什么是解构赋值?
解构赋值:ES6允许按照一定的模式从数组和对象中取值,然后进行对变量进行赋值,这被称为解构赋值。
解构赋值的分类:
一、数组解构赋值
简单的数组的解构
//例1:
{
let a,b;
[a,b]=[1,2];
console.log(a,b) //输出 a=1 b=2;
}
含有扩展运算符(…)的解构
//例2:
{
let a,b,c;
[a,b,...c]=[1,2,3,4,5,6];
console.log(a,b,c) //输出 a=1 b=2 c=[3,4,5,6];
}
当解构不成功或者解构不完全的时候
// 例3:
{
let a,b,c;
[a,b,c]=[1,2];
console.log(a,b,c);//输出 a=1 b=2 c=undefined;
}
//例4:
{
let a,b;
[a,b]=[1,2,3];
console.log(a,b);//输出 a=1 b=2;
}
数组的解构赋值,要求等号两边的结构格式要相同,才能完全结构。
上面代码例子1:
其中[a,b]=[1,2],两边的结构是完全相同的,那么就完全解构,1赋值给a,2赋值给b。
例子代码2:
其中引入新的运算符-----扩展运算符(…),用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中。[a,b,…c]=[1,2,3,4,5,6],1赋值给a,2赋值给b,加了扩展运算符的c,那么…c=[3,4,5,6],这就是扩展运算符。
例子代码3:[a,b,c]=[1,2],a,b会挨个被赋值为1,2,但是等号右边已经没有值了,那么c就是已经定义了,但是这里没有赋值给它,那么c等于undefined。
例子代码4:右边多了数值,就会自动丢弃,不会赋值给左边的变量。
默认值
//例子5:
{
let foo;
[foo=12]=[];
console.log(foo) //输出 12;
}
//例子6:
{
let[x,y="b"]=["a",undefined]// x="a" ,y="b"
}
//例子7
{
let a=2;
[a]=["undefined"];
console.log(a); //输出 a="undefined"
}
解构赋值是允许设定默认值的,但是只有undefined才会触发使用默认值。
例子代码5:[foo=12]=[],因为右边是一个空的,没有值,那么右边就相当于undefined,那么就会触发使用foo的默认值12,所以输出12。
例子代码6:[x,y=“b”]=[“a”,undefined],x会被赋值为字符串“a”,因为y对应过去是undefined,那么触发使用默认值,所以y=“b”。
例子代码7:如果是这种“undefined”的话,那么就不会触发默认值,“undefined”就是一个字符串。
解构顺序
//例子8
{
let[x=1,y=x]=[2]
console.log(x,y) // x=2 y=2
}
先把2赋值给x,这时x已经是2了,再进行对y的解构赋值,因为是undefined,那么触发使用默认值,y=x,这时x=2,那么y=2。这就是数组解构赋值的顺序。
二 、对象的解构赋值
对象的解构赋值与数组有一个重要的不同。数组的元素是按顺序进行排列的,变量的取值是由它的位置决定的,而对象的属性是没有次序的,变量必须与属性同名,而且等号两边的结构和格式是一模一样的,这样才能取到正确的值。
例如:
//例子9
{
let {bar,foo}={foo:"aaa",bar:"bbb"}
console.log(foo,bar); //输出 foo="aaa" bar="bbb"
}
//例子10
{
let {baz}={foo:"aaa",bar:"bbb"};
console.log(baz);//输出 undefined
}
//例子11
{
let{x,y,z=1,a:q}={a:100,b:200,y:300}
console.log(x,y,z,q);// x=undefined y=300 z=1 q=100
}
上面代码的第一个例子中,等号左边与等号右边变量的次序没有挨着次序对齐,但是对象的解构赋值是不影响的,是通过属性名来进行赋值的。
第二个代码例子的变量没有对应相同的属性名,导致取不到值,最后就等于undefined。
上述两个例子的书写都是对象解构赋值的简写。实际上:
{
let {bar:bar,foo:foo}={foo:“aaa”,bar:“bbb”}
console.log(foo,bar); //输出 foo=“aaa” bar=“bbb”
}
对象的解构赋值的内部机制是先找到相同属性名的,然后进行赋值给对应的变量,其实真正被赋值的是后者,而不是前者。
例如:
//例子12
{
let{foo:baz}={foo:"aaa",bar:"bbb"};
console.log(baz);//输出 baz="aaa"
console.log(foo);//输出 将会报错 error:foo is not defined
} //foo是一个属性名而不是一个变量,赋值是baz被赋值“aaa”。
三、字符串的解构赋值
字符串也可以进行解构赋值,这时候的字符串就被转换为一个类似数组的对象。
{
let[a,b,c,d,e]="hello";
console.log(a,b,c,d,e); //输出 a="h" b="e" c="l" d="l" e="o"
}
类似数组的对象都有一个length属性,同时还可以对这个属性进行解构。
例如
{
let{length:len}="hello";
console.log(len); //输出 len=5
四、圆括号问题
以下三种解构赋值不得使用圆括号。
1.变量声明语句
let [( a )]=[1];
let {x: ( c )}={};
let {(x: c)}={};
let {(x):c}={};
以上语句都会报错,因为都是变量声明语句。
2.函数参数
function f([(z)]){ return z;} 报错
function f([z,(x)]){ return x;} 报错
因为函数参数也属于变量声明。
3.赋值语句的模式
({p:a})={p:10}; 报错
([a])=[5]; 报错
上面语句把整个模式放在圆括号里,导致报错。
那么可以使用圆括号的情况
例如
[(b)]=[3]; 正确
({p:(d)}={}); 正确
[(parseInt.prop)]=[3] 正确
上面三行语句都可以正确执行,因为首先它们都是赋值语句,而不是声明语句;其次它们的圆括号都不属于模式的一部分。第一行语句中,模式是取数组的第一个成员,跟圆括号无关;第二行语句中,模式是p,而不是d;第三行语句与第一行语句的性质一致。
五、用途和运用场景
交换变量的值
以往的变量交换需要中间变量来暂时存储值,显得复杂。
利用解构赋值交换变量
例如
{
let x=1;
let y=2;
[x,y]=[2,1];
console.log(x,y)// 输出 x=2 y=1;
}
从函数返回多个参数
函数只能返回一个值,如果想返回多个值,只能把它们放在数组和对象里返回,有了解构赋值,从中取值就更加的方便。
例如
{
function f1(){
return [1,2,3]
}
let [a,b,c]=f1(); //输出 a=1 b=2 c=3
}
{
function f2(){
return{
foo:1,
bar:2
};
};
let {foo,bar}=f2(); //输出 foo=1 bar=2
}
提取JSON数据
在后台服务器传输来的数据,大多是JSON格式,那么要提取有用的数据,用解构赋值就会非常的容易。
例如
{
let jsonData={
id:42,
status:"OK",
data:[867,5309]
};
let{id,status,data:number}=jsonData;
console.log(id,status,number)// 输出 42 OK [867,5309]
}
其他
比如数据的提取与舍去
{
let [b,,,c]=[1,2,3,4]
console.log(b,c);//输出 b=1 c=4;
}
{
let [a,...b]=[1,2,3,4,5]
console.log(a,b); //输出 a=1 b=[ 2, 3, 4, 5 ]
}