变量的解构赋值
目录
1. 数组的解构赋值
以前为变量赋值,只能直接指定值。
// 直接指定值
let a = 1;
let b = 2;
let c = 3;
ES6 允许通过解构进行赋值。
let [a, b, c] = [1, 2, 3];
a; // 1
b; // 2
c; // 3
上面代码中,a
,b
,c
三个变量,按照数组中对应位置上的值被赋值。
还可以对嵌套数组进行解构赋值。
// 对嵌套数组进行解构赋值
let [x, [[y], z]] = [1, [[2], 3]];
x; // 1
y; // 2
z; // 3
// 对数组部分数据进行解构赋值
let [ , , third] = ["hello", "world", "!"];
third // "!"
let [x, ...y] = [1, 2, 3, 4];
x; // 1
y; // [2, 3, 4]
解构不成功,变量的值就等于undefined
。
let [x, y] = ['a'];
x; // "a"
y; // undefined
let [x] = [];
let [y, z] = [1];
x; // undefined
y; // 1
z; // undefined
注意:
ES6 内部使用严格相等运算符(===
),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined
,默认值才会生效。
不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。解构依然成功。
let [x, y] = [1, 2, 3, 4];
x; // 1
y; // 2
// 嵌套数组不完全解构
let [a, [b], d] = [1, [2, 3], 4];
a; // 1
b; // 2
d; // 4
默认值
解构赋值允许指定默认值。
// 指定默认值
let [flag= true] = [];
foo; // true
let [x, y = 'b'] = ['a'];
x; // 'a'
y; // 'b'
let [x, y = 'b'] = ['a', undefined];
x; // 'a'
y; // 'b'
默认值可以是一个表达式,但是这个表达式是惰性求值的,即只有在用到的时候,才会求值。
function f() {
return 'Hello World!'
}
let [x = f()] = [1];
x; // 结果为1,函数不会执行
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [x = 1, y = x] = []; // x=1; y=1
let [x = y, y = 1] = []; // ReferenceError: y is not defined
2. 对象的解构赋值
对象也可以进行解构赋值。
let { name, age} = { name: 'jidi', age: 22 };
name; // "jidi"
age; // 22
对于对象的解构,变量名次序不必像数组一样保持一致(数组元素按照次序排列,位置决定取值),只要变量与属性同名,才能取到正确的值,否则会取不到值,返回undefined
。
let { name, age} = { age: 22, name: 'jidi' };
name; // "jidi"
age; // 22
// 对象属性中找不到与变量名一致的属性,则值为undefined
let { sex} = { name: 'jidi', age: 22 };
sex; // undefined
对象解构赋值失败,变量的值为undefined
。
let { sex} = { name: 'jidi' };
sex; // undefined
对象解构赋值允许变量名与属性名不一致,但是必须写成下面样子。
let { name: xingming } = { name: 'jidi' };
xingming; // "jidi"
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f; // 'hello'
l; // 'world'
对象的解构赋值也可以用于具有嵌套结构的对象。
let person = {
man: [
{ sex: '男' }
],
woman: [
{ sex: '女' }
]
};
let { man: [{ x }], woman: [{ y }]} = person;
x; // { sex: '男' }
y; // { sex: '女' }
上述例子中,man
和woman
此时不是变量,而是模式,不会被赋值。如果也要被赋值,需要写成下面样子。
let { man, man: [{ x }], woman, woman: [{ y }]} = person;
下面是另一个例子。
const example= {
first: {
second: {
name: 'jidi',
age: 22
}
}
};
let { first, first:{ second }, first:{ second: name }, first:{ second: age }} = example;
first; // { second: { name: 'jidi', age: 22 }}
second; // { name: 'jidi', age: 22 }
name; // 'jidi'
age; // 22
对象的解构赋值可以取到继承的属性。
const x= {};
const y= { name: 'jidi' };
// 将对象y设置为对象x的原型对象,对象x会继承原型对象y的属性name
Object.setPrototypeOf(x, y);
const { name} = x;
name; // 'jidi'
默认值
对象的解构也可以指定默认值。默认值生效的条件是,对象的属性值严格等于undefined
。
var { x = 3 } = {};
x; // 3
var {x, y = 5} = {x: 1};
x // 1
y // 5
注意:
由于数组是一个特殊的对象,因此可以对数组进行对象属性的解构。
let arr = [1, 2, 3];
let { 0 : first, [arr.length - 1] : last, length } = arr;
first; // 1
last; // 3
length; // 3
3. 字符串的解构赋值
也可以对字符串进行解构赋值,可以把字符串看成是一个类似数组的对象。
const [x, y, z] = 'you';
x; // 'y'
y; // 'y'
z; // 'u'
4. 数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
let { toString: s } = 123;
s === Number.prototype.toString; // true
let { toString: s } = true;
s === Boolean.prototype.toString; // true
注意:
对undefined
和null
进行解构赋值,都会报错。
5. 函数参数的解构赋值
函数的参数也可以使用解构赋值。
// 例子一
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
// 例子二
[[1, 2], [3, 4]].map(([a, b]) => a + b); // [ 3, 7 ]
函数参数的解构也可以使用默认值。
function move({ x = 0, y = 0 } = {} ) {
return [x, y];
}
move({ x: 3, y: 8 }); // [3, 8]
move({ x: 3 }); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
6. "()"的使用
对编译器来说,一个式子到底是模式,还是表达式,没有办法从一开始就知道。ES6 的规则是:只要有可能导致解构的歧义,就不得使用圆括号。
不能使用 "()"的情况
属于下面情况的,都不能使用圆括号。
1.变量声明语句
// 在变量声明语句中使用(),全部报错
let [(x)] = [1];
let { x: (y) } = {};
let ({ x: y }) = {};
let { (x: y) } = {};
let { (x): y } = {};
let { x: ({ y: y }) } = { x: { y: 2 } };
2.函数参数
函数参数也属于变量声明,也不能使用圆括号。
// 函数参数解构赋值使用()报错
function f([(x)]) { return x; }
function f([x,(y)]) { return x; }
3.赋值语句的模式部分
// 赋值语句的模式部分使用(),全部报错
({ x: y }) = { x: 'jidi' };
([x]) = [5];
能使用 "()"的情况
能使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。
[(b)] = [3];
({ p: (d) } = {});
[(parseInt.prop)] = [3];
上面都可以执行,因为都是赋值语句,且模式部分没有被()
包含。
7. 参考链接
本篇博文是我自己学习笔记,原文请参考:ECMAScript 6 入门
如有问题,请及时指出!
欢迎沟通交流,邮箱:[email protected]。