1.数组的解构赋值
基本用法:
ES6允许按照一定模式从对象和数组中提取值,然后对变量进行赋值,称为解构;数组解构赋值本质上是一种模式匹配,只要等号两边的模式相同,左边的变量就会被赋予对应的值;
<script>
let [a,b,c] = [1,2,3];
console.log(a,b,c); // 1 2 3
// 只要等号两边的模式匹配,就能完成解构赋值
let [, , third] = ["aa","bb","cc"];
console.log(third);// cc
let [one,[two,[three]]] = [1,[2,[3]]];
console.log(one,two,three);
</script>
如果解构不成功,变量的值为undefined;不完全解构:等号左边的模式只能匹配一部分等号右边的数组,此时依然能够解构成功;
// 不完全解构
let [aaa,bbb] = [111,222,333];
console.log(aaa,bbb); // 111 222
如果等号右边不是数组(严格来说是不可遍历的结构),将会报错,如1、false、NaN、null、undefined、{},这些值转换为对象以后不具备Iterator接口(前5个),或者本身就不具备遍历器(最后一个);结合上一条,也可以认为只要是具有Iterator接口的数据结构,都可以采用数组形式解构赋值;
默认值:
解构赋值允许设置默认值:在等号右边能匹配到值的前提下,默认值无效;
// 解构赋值的默认值设置
let [d = 1] = [];
console.log(d);// 1
let [x = 1] = [undefined];
x // 1
let [x = 1] = [null];// null 不全等与undefined
x // null
ES6内部用全等判断一个位置是否有效,因此如果一个数组成员如果不是全等于undefined,默认值是无效的;如果一个默认值是一个表达式,那么该表达式是惰性求值的,即只有在用到默认值时才会求值;
let [a
= fn()] = [];
let [b
= fn()] = [222];
function fn(){
return 1;
}
console
.log(a
,b
);
默认值还可以是等于一个其他变量,前提是该变量必须已经声明;
// 默认值也可以是其他变量(该变量需要已经被声明)
let [x = 1 , y = x] = [];
console.log(x,y);// 1 1
let [w = z , z = 1] = []
console.log(w); // 报错,z还未声明
2.对象的解构赋值
对象解构与数组解构有一个重要不同:数组中的元素是按次序排列的(变量取值由位置决定),但是对象的属性是无序的,要赋值的变量需要跟属性同名才能取到正确的值;对象解构赋值的内部机制是先找到同名属性,然后再赋值给相应地变量,真正被赋值的是后者;常见的两种情况:
变量名等于对象中的属性名;变量名不等于对象中的属性名;
let { a
, b
} = {a
:1 , b
: 2};
console
.log(a
,b
);
let{first
: f
, last
: l
} = {first
: 3 , last
: 4};
console
.log(f
,l
);
与数组一样,对象解构也可以嵌套使用;
let obj
= {
p
: [
"hello",
{ y
: "world"}
]
}
let { p
: [x
,{y
}]} = obj
;
console
.log(x
+ y
);
可以设置默认值,生效的前提是对象的属性值严格等于undefined;
let {q
,w
= 1} = {q
: 11 , w
: undefined
};
console
.log(q
,w
);
解构赋值允许左边的模式之中不放置任何变量名;对象解构可以很方便的将现有对象的某个方法赋值给变量;
let {random
,floor
} = Math
;
console
.log(random
);
数组本质是特殊的对象,因此可以对数组进行对象属性的解构;
// 数组本质是特殊的对象,因此可以对数组进行对象属性的解构
const arr = [1,2,3,4,5,6];
let {0 : first , [arr.length - 1] : last} = arr;
console.log(first,last);// 1 6
3.字符串的解构赋值
字符串也可以解构赋值,此时字符串被转换成一个类似数组的对象(伪数组);
const str = "hello";
let [a,b,c,d,e] = str; // 此时该字符串被转化成一个伪数组,具有length属性但是没有数组的方法
console.log(a,b,c,d,e); // h e l l o
4.数值和布尔值的解构赋值
在使用数值和布尔值进行解构赋值时,数值(==>Number)和布尔值(==>Boolean)会先转换成对象;解构赋值的规则是:只要等号右边的值不是数组或对象,会先将其转换成对象;undefined和null无法转换成对象,所以不能对他们进行解构赋值;
// 数值和布尔值,会先被转换成对象再进行赋值
let {toString : s} = 1;
let {toString : b} = true;
// 判断s和b的toString的值是否等于对象的toString方法
console.log(s === Number.prototype.toString); // true
console.log(b === Boolean.prototype.toString); // true
5.函数参数的解构赋值
函数参数也能使用解构赋值;函数参数解构能使用默认值(同样,undefined值能触发默认值);
// 函数参数使用解构赋值
function add([x,y]) {
console.log(x + y);
}
add([1,2]); // 3
let res = [[1,2],[3,4]].map(([a,b]) => a + b); // map遍历数组,并返回回调函数处理结果组成的新数组
console.log(res);//[3,7]
// 可以使用默认值
function move({x = 0,y = 0}) {
return [x,y];
}
let res1 = move({x : 1 , y : 2});
let res2 = move({x : 1 });
let res3 = move({});
console.log(res1); // [1, 2]
console.log(res2); // [1, 0]
console.log(res3); // [0,0]
6.圆括号问题
对于编译器而言,如何分别一个式子是表达式还是模式,没有办法在一开始就对此作出判断,只有在解析到(或解析不到)等号时才能确定;因此,只要有可能引起解构歧义,就不要使用圆括号;建议:只要有可能,就不要在模式中使用圆括号;简单来说,只要是将模式放到圆括号中,都是非法的;
不能使用圆括号的情况:
变量声明语句:
// 1.变量声明语句不能使用圆括号
let [(a)] = 1;
let {(a) : 1} = {};
函数参数(也属于变量声明):
// 2.函数参数
function test([(a)]) {
// 哈哈哈哈哈
}
赋值语句的模式:
// 3.赋值语句中的模式
({ p : a })= { p :44};
可以使用圆括号的情况:
赋值语句的非模式部分可以使用圆括号:
[(a
)] = [3];
console
.log(a
);
({p
: (b
)} = {p
: 4});
console
.log(b
);
7.用途
交换变量的值:
let a
= 1;
let b
= 2;
[a
,b
] = [b
,a
];
console
.log(a
,b
);
从函数返回多个值:
function test() {
return [1,2,3];
}
let [c
,d
,e
] = test();
console
.log(c
,d
,e
);
定义函数参数:
function fn1([g
,h
]) {
console
.log(g
,h
);
}
fn1([1,2]);
function fn2({one
: name
, two
: age
}) {
console
.log(name
,age
);
}
fn2({one
: "peanut",two
: 88});
提取JSON数据:
let jsonData
= {
name
: "peanut",
age
: 33,
learning
: ['javascript','less']
}
let {name
,age
,learning
: subject
} = jsonData
;
console
.log(name
,age
,subject
);
设置函数参数默认值: 比如设置jQuery中ajax方法的参数默认值;
遍历map结构
let map
= new Map();
map
.set("first","peanut");
map
.set("second","test");
for(let [key
,value
] of map
) {
console
.log(key
+ " " + value
);
}
for(let [key
] of map
){
console
.log(key
);
}
for(let [,value
] of map
){
console
.log(value
);
}
输入模块指定的方法
// 输入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");