解构赋值
ES6中引入了解构赋值的概念,解构赋值遵循 “模式匹配” ,即只要等号两边的模式相等,左边的变量就会被赋予对应的值。不同类型数据的解构方式不同。
1.数组解构
具有 Iterator 接口的数据结构,都可以采用数组形式的解构赋值。
const [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo, bar, baz) // 输出结果:1 2 3
ES6对数组进行解构,并依次赋值变量foo、bar、baz。数组的解构赋值按照位置将值与变量对应。
数组还可以实现不完全解构,只解构部分内容:
const [x, y] = [1, 2, 3]; // 提取前两个值
const [, y, z] = [1, 2, 3] // 提取后两个值
const [x, , z] = [1, 2, 3] // 提取第一三个值
如果解构时对应的位置没有值就会将变量赋值为undefined:
const [x, y, z] = [1, 2];
console.log(z) // 输出结果:undefined
数组解构赋值可以使用rest操作符来捕获剩余项:
const [x, ...y] = [1, 2, 3];
console.log(x); // 输出结果:1
console.log(y); // 输出结果:[2, 3]
在解构时还支持使用默认值,当对应的值为undefined时才会使用默认值:
const [x, y, z = 3] = [1, 2];
console.log(z) // 输出结果:3
2.对象解构
对象的解构赋值的本质其实是先找到同名的属性,在赋值给对应的变量:
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
console.log(foo, bar); // 输出结果:aaa bbb
需注意的是,在js中对象的属性是没有顺序的。所以在解构赋值时,变量必须与属性同名才能去取到值。
对象的解构赋值也是支持默认值的,当定义的变量在对象中不存在时,其默认值才会生效:
let { foo, bar, baz = 'ccc'} = { foo: 'aaa', bar: 'bbb', baz: null };
console.log(foo, bar, baz); // 输出结果:aaa bbb null
let { foo, bar, baz = 'ccc'} = { foo: 'aaa', bar: 'bbb' };
console.log(foo, bar, baz); // 输出结果:aaa bbb ccc
可以看到,只有定义的变量是严格的 ===undefined 时,它的默认值才会生效。
除此之外,我们还需要注意,不能给已声明的变量进行赋值,因为当缺少 let、const、var 关键词时,将会把{baz}
理解为代码块从而导致语法错误,所以下面代码会报错:
let baz;
{ baz } = { foo: 'aaa', bar: 'bbb', baz: 'ccc' };
可使用括号包裹整个解构赋值语句来解决上述问题:
let baz;
({ baz } = { foo: 'aaa', bar: 'bbb', baz: 'ccc' });
console.log(baz)
在对象的解构赋值中,可以将现有对象的方法赋值给某个变量,比如:
let { log, sin, cos } = Math;
log(12) // 输出结果:2.4849066497880004
sin(1) // 输出结果:0.8414709848078965
cos(1) // 输出结果:0.5403023058681398
3.其他解构赋值
(1)字符串解构
字符串解构规则:只要等号右边的值不是对象或数组,就先将其转为类数组对象,在进行解构:
const [a, b, c, d, e] = 'hello';
console.log(a, b, c, d, e) // 输出结果:h e l l o
类数组对象有 length 属性,因此可以给这个属性进行解构赋值:
let {length} = 'hello'; // 输出结果: 5
由于字符串都是一个常量,所以我们通常是知道它的值是什么的,所以很少会使用变量的解构赋值。
(2)数值和布尔值解构赋值
对数值和布尔值进行解构时,它们将会先被转为对象,然后再应用解构语法:
let {toString: s} = 123;
s === Number.prototype.toString // 输出结果:true
let {toString: s} = true;
s === Boolean.prototype.toString // 输出结果:true
注意null和undefined不能转换为对象,所以如果右边是这两个值,就会报错。
(3)函数参数解构赋值
函数参数表面上是一个数组,在传入参数的那一刻,就会被解构为x和y。
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
除此之外,我们还可以解构函数的返回值:
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
总结 - 划重点
解构赋值的三个条件
1.两边结构必须一样
2.等式右边必须有意义
3.赋值和解构要同时完成
let {a,b} = {a:12,b:5,c:9}
console.log(a,b)//12 5
let [c,d] = [2,3]
console.log(c,d)//2 3
let {e,f} = [4,5]
console.log(e,f)//undefined undefined
let {g,h} = {4,5}
console.log(g,h)//报错 等式右边啥玩意都不是
let {i,j} = {i:4,j:5}
console.log(i,j)//4 5
let {k,l};
{k,l} = {k:1,l:2};
console.log(k,l);//报错 解构声明缺少初始化的对象 可使用括号包裹整个解构赋值语句来解决