一、数组解析赋值
1.ES6允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
let [a,b,c]=[1,2,3];
a;//1
b;//2
c;//3
2.模式匹配,只要等式两边的模式相同,左边的变量就会被赋予对应的值。
let [a,[b],[[c]]]=[1,[2],[[3]]];
a;//1
b;//2
c;//3
let [,a,,b,c]=[1,2,3,4,5];
a;//2
b;//4
c;//5
let [a,...b]=[1,2,3,4,5];
a;//1
b;[2,3,4,5]
let [x,y,...z]=[1];
x;//1
y;//undefined
z;//[]
3.解构不成功,变量的值就为undefined。
let [a]=[];
a;//undefined
let [a,b]=[1];
a;//1
b;//undefined
4.不完全解构,等号左边的模式只匹配一部分等号右边的数组,依然可以解构成功。
let [a,[,b],[c]]=[1,[1,2,3],[1]];
a;//1
b;//2
c;//1
5.等号右边的值,要么本身具备Iterator的接口,要么转为对象后具备Iterator接口,否则会报错。
/以下赋值语句都会报错
let [a,b,c]=123;
let [a,b,c]=NaN;
let [a,b,c]=null;
let [a,b,c]=undefined;
let [a,b,c]=false;
let [a,b,c]={};
6.只要某种数据结构具有Iterator接口,都可以使用数组形式的解构赋值。
let [x,y,z]=new Set([1,2,3]);
x;//1
y;//2
z;//3
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
7.解构赋值允许指定默认值。只有当等式右边的值===undefined时,默认值才生效。
let [a=1,b=2,c=3,d=4]=[0,null,undefined];
a;//0
b;//null
c;//3
d;//4
8.如果默认值是一个表达式,表达式是惰性求值的,只有用到时才会执行。
function f(){
console.log("ssssss");
}
let [a=f()]=[1];//发f()不会执行,因为a被成功赋值,并不会执行求取默认值的操作
9.默认值可以引用解构赋值的其它变量,前提是该变量已经声明,否则会报错。
let [x=1,y=x]=[];//正确
let [x=y,y=1];[];//错误,y做x默认值时还没有声明
二、对象解构赋值
1.解构不仅可以用于数组,还可以用于对象。
let {a,b,c}={a:1,b:2,c:3};
a;//1
b;//2
c;//3
2.数组元素是按次序排列的,变量的取值是由它的位置决定的;对象元素没有次序,变量的取值根据对象的属性名来决定,变量必须与属性同名,才能得到正确的值。
let {bar,foo,baz}={foo:"foo",bar:"bar"};
bar;//bar
foo;//foo
baz;//unfefined
3.变量名也可以和属性名不一样,同样可以赋值。
let {foo:f,bar:baz}={foo:"f",bar:"baz"};
f;//f
baz;//baz
所以对象解构赋值的内部机制实际上是先找到同名属性,再赋值给对应的变量。
let {foo,bar}={foo:"foo",bar:"bar"} 等价于 let{foo:foo,bar:bar}={foo:"foo",bar:"bar"}
let {bar:baz}={bar:"bar"}
bar是匹配的模式,baz是变量。先根据bar找到对应的模式,再赋值给变量baz。
4.与数组一样,解构可以用于嵌套结构的对象。
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"
5.对象的解构也可以指定默认值,默认值生效的条件是,对象的属性值严格等于undefined。
let {x=123,y="abc"}={x:"456"}
x;//456
y;//abc
6.如果解构是嵌套的对象,而且子对象所在的副属性不存在,那么将会报错。
//报错 foo值为undefined,再取子属性就会报错
let {foo:{bar}}={};
7.JavaScript会将放在行首的大括号理解成一个代码块,应该小心对一个声明的变量解构赋值。
let foo;
{foo}={foo:"foo"}//报错
({foo}={foo:"foo"})//正确
8.对象的解构赋值,可以很方便的将一个对象的方法赋值给变量。
let {log,sin,cos}=Math
9.对象本质上是特殊的对象,可以对数组进行对象属性的解构。
let arr["foo","bar","baz"];
let {0:foo,1:bar,2:baz}=arr;
foo;//foo
bar;//bar
baz;//baz
三、对象的解构赋值
1.字符串也可以解构赋值,此时,字符串转化为一个类数组的对象。
let str="12345";
let [a,b,c,d,e]=str;
a;//1
...
3;//5
2.类数组的对象都有一个length的属性,可以对这个属性解构赋值。
let str="12345";
let {length}=str;
length;//5
四、非对象,数组解构赋值
1.解构赋值时,如果等号右边是数值或布尔类型,则会先转化为对象。数值,布尔类型的包装对象都有toString的属性。
let {toString:s}=123;
s//Number.property.toString
let {toString:s}=true;
s//Boolean.property.toString
2.如果等号右边的值不能转化为对象,则会报错。
let {prop}=null;//报错
let {prop}=undefined;//报错
五、函数参数的结构赋值
1.函数参数也可以使用解构赋值。
function func([a,b]){
let c=a+b;
console.log("a+b="+c);
}
func([2,3]);//5
function func({a,b}){
let c=a+b;
console.log("a+b="+c);
}
func({a:2,b:3})/5
2.函数解构赋值也可以有默认值
function func([a=0,b=0]){
let c=a+b;
console.log("a+b="+c);
}
func();//0
function func({a=0,b=0}){
let c=a+b;
console.log("a+b="+c);
}
func({})//0
五、解构用途
1.交换变量的值
let a=2;
let b=3;
[a,b]=[b,a];
2.从函数返回多个值
//返回一个数组
function func(){
return [1,2,3];
}
let [a,b,c]=func();
//返回一个对象
function func(){
return {
a:1,
b:2,
c:3
}
}
let {a,b,c}=func();
3.函数参数的定义
//函数参数是有序列的值
function func([a,b,c]){...};
func([1,2,3]);
//函数参数是无序列的值
function func({a,b,c}){...};
func({b:"b",c:"c",a:"a"});
4.提取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]
5.函数参数的默认值
//函数参数是有序列的值
function func([a=1,b=2,c=3]){...};
func();
//函数参数是无序列的值
function func({a="a",b="b",c="c"}){...};
func();
6.遍历Map结构
let map=new Map();
map.set("first","hello");
map.set("second","world");
for(let [key,value] of map){};
for(let [key] of map){};
for(let [,value] of map);
7.输入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");