解构赋值
从数组中提取值,按照对应位置,对变量赋值
只要等号右边的值不是对象或数组,就先将其转为对象。
由于 undefined 和 null 无法转为对象,所以对它们进行解构赋值,都会报错
let [a, b, c] = [1, 2, 3];
只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值
应用:
const person = {
name: 'RyenToretto',
age: 22,
sex: '男'
}; // 解构赋值
const {name, age, sex} = person; // 缺点: 必须同名属性 console.log(name. age, sex); // 对比之前,明显好用了很多
console.log(person.name, person.age, person.sex);const arr = [1, 3, 5, 7, 9]; const [a, b, c, d, e, f=-1] = arr; // 是一组有序的赋值, 允许默认赋值 此时 f=-1,因为索引值为 undefined
const [aa, , cc] = arr; // aa=1, cc=5- 如果解构不成功,变量的值就等于undefined。
- 以下会报错
//右边的值 转为对象以后不具备 Iterator 接口
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null; let [foo] = {}; // {} 本身就不具备 Iterator 接口
- 解构赋值允许指定默认值
let [foo = true] = [];
foo // true let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
注意,ES6 内部使用严格相等运算符(===
),判断一个位置是否有值
所以,只有当一个数组成员严格等于undefined
,默认值才会生效。
let [x = 1] = [undefined];
x // let [x = 1] = [null];
x // null
如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值
function f() {
console.log('aaa');
} let [x = f()] = [1]; // 由于 x 可以取 1 ,所以函数 f() 不会被执行- 默认值可以引用解构赋值的其他变量,但该变量必须已经声明
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] = []; // Reference Error: y is not defined- 对象的解构赋值
-
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"实际上的完整写法: let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
- 也可以指定 默认值,生效的条件是,对象的属性值严格等于 undefined
var {x = 1, y = 2} = {x: 1}
console.log(x); //
console.log(y); //- 很有用的,sin(90*Math.PI/180);
let { log, sin, cos } = Math;
console.dir(Math);
console.dir(sin); // let {sin} = {sin:function(){}, cos:function(){}}- 由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
console.log(first); //
console.log(last); //- 字符串的解构赋值
此时,字符串被转换成了一个类似数组的对象
const [a, b, c, d, e] = 'hello';
console.log(a); // "h"
console.log(b); // "e"
console.log(c); // "l"
console.log(d); // "l"
console.log(e); // "o"- 类似数组的对象都有一个 length 属性,因此还可以对这个属性解构赋值 0
let {length : len} = 'hello';
console.log(len); //- 等号右边是数值和布尔值,则会先转为对象
let {toString: s} = 123;
console.log(s === Number.prototype.toString); // true let {toString: s} = true;
console.log(s === Boolean.prototype.toString); // true- 函数的 实参 与 形参 也可以进行 解构赋值
function add([x, y]){
return x + y;
} add([1, 2]); //- 函数 参数默认值 对象传参 参数是一组无序的值
function add({name = "someone", age = -1} = {name:"kjf", age:"22"}) {
return [name, age];
} console.log(add({name:"Jack", age:"31"})); // ["Jack", "31"]
console.log(add({name:"Rose", age:"21"})); // ["Rose", "21"]
console.log(add({})); // ["someone", -1]
console.log(add()); // ["kjf", "22"]- 函数 参数默认值 数组传参 参数是一组有序的值
function person([name="someone", age=-1] = ["kjf", 22]) {
return name + " : " +age;
} console.log(person(["Jack", 30])); // 'Jack : 30'
console.log(person(["Rose"])); // 'Rose : -1'
console.log(person([])); // 'someone : -1'
console.log(person()); // 'kjf : 22'
应用:
- 交换变量的值
let x = 1;
let y = 2; [x, y] = [y, x];- 快速提取 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]- for(let [attr1, attr2] of map){}
如此遍历 for(let [key, value] of map){}
任何部署了 Iterator 接口的对象,都可以用 for...of
循环遍历
// 获取键名
for (let [key] of map) {
// ...
} // 获取键值
for (let [,value] of map) {
// ...
}