学习来源:ES6入门教程
解构赋值
(1) 不同场景下的解构赋值
- 数组
- 基本用法
- “模式匹配”:只要等号两边的模式相同,左边的变量就会被赋予对应的值。如果解构不成功,变量的值就等于undefined。比如:let [foo, [[bar], baz]] = [1, [[2], 3]];
- 不完全解构:即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。
- 如果等号右边是不可遍历的结构,就会报错
- 事实上只要某种数据结构具有Iterator接口就都可以采用数组形式的解构赋值,比如还有set、Generator函数也可以使用数组形式的解构赋值
- 默认值
- 解构赋值允许指定默认值,但ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。
- 默认值可以是表达式,对表达式是惰性求值,只有在要用到的时候才会取值。比如let [x = f()] = [1] ,因为x能取到值,所以函数f根本不会执行。
- 默认值可以引用解构赋值的其他已经声明的变量,否则会报错
- 基本用法
- 对象
- 基本用法
- 变量名和属性名一致的情况
- 数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。比如:let { bar, foo } = { foo: ‘aaa’, bar: ‘bbb’ };如果解构失败变量的值等于undefined。还可以很方便的获取对象方法赋值给变量,比如:let { log, sin, cos } = Math;
- 变量名和属性名不一致的情况
- 对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。一致的时候直接简写对象属性就可以了,当不一致的就都要写出来,前者是模式,后者才是真正被赋值的变量
- 比如:let { foo: baz } = { foo: ‘aaa’, bar: ‘bbb’ }; foo是模式,输出值为undefined;baz输出值为“aaa”
- 解构可以用于嵌套结构的对象,并且如果也想给模式p也赋值可以写下面这样:
- 对象的解构赋值可以取到继承的属性。
- 变量名和属性名一致的情况
- 默认值
- 对象的解构也可以指定默认值,生效条件对象的属性值严格等于undefined,比如:var {x = 3} = {x : undefined}
- 注意点
- 如果要将一个已经声明的变量用于解构赋值,必须非常小心。避免将大括号写在行首,否则JS会将其解释为代码块;比如 let x; {x}={x:1}这种情况就会报错。正确写法:({x}={x:1})
- 解构赋值允许等号左边的模式之中不放置任何变量名,会出现非常古怪的赋值表达式,毫无意义但合法。比如({} = [true, false]); ({} = ‘abc’); ({} = []);等等
- 由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
- 基本用法
- 函数
- 函数的解构赋值主要应用在函数参数方面,还有给函数参数指定默认值,undefined就会触发函数参数的默认值。
//注意以下两种形式默认值的区别!!!
//形式一 注意这个是给想给变量x,y指定默认值
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]
//形式二 注意这个是给这个对象也就是函数参数指定默认值
function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
- 字符串
- 字符串会被转换成一个类似数组的对象,类似数组的对象都有一个length属性
- const [a, b, c, d, e] = ‘hello’; // a “h” b “e” …
- let {length : len} = ‘hello’; //len 5
- 数值和布尔值
- 解构赋值的规则只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
- let {toString: s} = 123; let { prop: x } = undefined; // TypeError;let { prop: y } = null; // TypeError
(2) 主要用途
- 交换变量的值 [x,y] = [y,x]
- 从函数返回多个值
- 函数参数的定义
- 函数参数的默认值
- 提取JSON的值
- 遍历Map结构
- 输入模块的指定方法
(3) 圆括号问题
由于圆括号会对解构赋值的解析产生歧义,因此,建议只要有可能,就不要在模式中放置圆括号。
- 可以使用圆括号的情况
- 只有一种:赋值语句的非模式部分,可以使用圆括号。({ p: (d) } = {}); // 正确
- 不能使用圆括号的情况
- 变量声明语句 比如:let [(a)] = [1];let {x: ©} = {};let ({x: c}) = {};let {(x: c)} = {};等等全部报错
- 函数参数 比如:function f([(z)]) { return z; } 因为函数参数也属于变量声明
- 赋值语句的模式