ES6读书简记·解构赋值

CY 2019年01月03日 722次浏览

解构赋值时ES6中很好用的一个特性,很多场景都会使用到。

变量的解构赋值

数组的解构赋值

let [a, b, c] = [1, 2, 3];

解构不成功,变量的值就等于undefined

let [foo, [[bar], baz]] = [1, [[2], 3]]; // bar 为 2
let [ , , third] = ["foo", "bar", "baz"]; // third 为 "baz"
let [head, ...tail] = [1, 2, 3, 4]; // tail 为 [2, 3, 4]
let [x, y, ...z] = ['a']; // y 为 undefined z为一个空数组[]
let [x, y] = [1, 2, 3]; // 不完全解构
let [x, y, z] = new Set(['a', 'b', 'c']); // Set的解构赋值

数组解构赋值的条件:如果等号的右边不是可遍历的结构将会报错,要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。

解构赋值可以指定默认值

只有当一个数组成员严格等于undefined默认值才会生效

let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

默认值可以引用解构赋值的其他变量,但该变量必须已经声明

let [x = y, y = 1] = [];     // ReferenceError: y is not defined

对象的解构赋值

对象的解构,变量必须与属性同名,才能取到正确的值,并不是看顺序,顺序可以不一样

如果解构失败,变量的值等于undefined

对象的解构赋值,可以很方便地将现有对象的方法赋值到某个变量

const { log } = console; // 将console对象的log方法赋值给log变量
log('hello') // hello

如果变量名与属性名不一致,必须写成下面这样。

let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; // 使用foo找到值,赋值给baz变量
baz // "aaa"
foo // error: foo is not defined

对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。 比如说上面的foo就报错了。上面的foo叫做模式baz叫做变量

当解构赋值用于嵌套对象的时候一定要分清哪里是模式,哪里是变量,一般嵌套的最内层是变量,外层全是模式,像下面这样:

const node = {
  loc: {
    start: {
      line: 1,
      column: 5
    }
  }
};

let { loc, loc: { start }, loc: { start: { line }} } = node;
line // 1
loc  // Object {start: Object}
start // Object {line: 1, column: 5}

上面的三次赋值,分别赋值了locstartline

可以把值赋值给其他对象或数组

let obj = {};
let arr = [];

({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });

obj // {prop:123}
arr // [true]

如果解构模式是嵌套的对象,但是子对象所对应的父属性不存在,那么将会报错。

对象的解构赋值可以取到继承的属性

对象解构赋值的默认值

对象的解构也可以指定默认值,只要给变量指定默认值就行,不要把默认值指定给了模式。 默认值生效的条件是,对象的属性值严格等于undefined

解构赋值的注意点

  • 如果要将一个已经声明的变量用于解构赋值,必须非常小心 。
// 正确的写法
let x;
({x} = {x: 1});

如果不加上面的圆括号就会报错。

  • 解构赋值允许等号左边的模式之中,不放置任何变量名,空空如也。

  • 由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr; // 方括号中属于“属性名表达式”
first // 1
last // 3

字符串的解构赋值

let {length : len} = 'hello';
len // 5

数值和布尔值的解构赋值

解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefinednull无法转为对象,所以对它们进行解构赋值,都会报错。

函数参数的解构赋值

下面的写法很骚,但是很实用。

[[1, 2], [3, 4]].map(([a, b]) => a + b);

函数参数的解构也可以使用默认值,这个在函数扩展那一章节里面有讲。

解构赋值中使用圆括号

可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。

首先是赋值语句,而不是声明语句let, var...);其次它们的圆括号不属于模式的一部分(模式上面有说)。

解构赋值的骚操作

交换变量的值

let x = 1;
let y = 2;
[x, y] = [y, x];

从函数返回多个值

函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。

函数参数的定义

解构赋值可以方便地将一组参数与变量名对应起来,比如说赋值给一个方法的参数为一个对象,这个时候可以使用解构赋值来拆分为多个参数。

提取 JSON 数据

服务器返回一个JSON数据,就可以使用解构赋值,更加方便的获取需要的值。

函数参数的默认值

可以使用解构赋值的默认值来为函数的参数指定默认值。

遍历 Map 结构

const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for (let [key, value] of map) {
  console.log(key + " is " + value);
}
// first is hello
// second is world
// 只获取键名
for (let [key] of map) {
  // ...
}

// 只获取键值
for (let [,value] of map) {
  // ...
}

输入模块的指定方法

这个在模块开发中很常用。

const { SourceMapConsumer, SourceNode } = require("source-map");