解构赋值

数组的解构赋值

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

var a = 1;
var b = 2;
var c = 3;

ES6允许写成下面这样。
var [a, b, c] = [1, 2, 3];

这种写法有点像‘模式匹配’,如果匹配不成功就会返回'undefined'。

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []

如果左边只匹配右边部分值,仍是解构成功。 只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值。

数组可以使用默认值,只要数组成员不严格等于undefined

对象的解构赋值

解构不仅可以用于数组,还可以用于对象。 对象的解构赋值与数组的不同,对象的解构赋值变量必须与属性同名。

var { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

这实际上说明,对象的解构赋值是下面形式的简写:

var { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };

对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

var { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined

foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo

对象的默认值生效的条件是,对象的属性值严格等于undefined

嵌套的对象解构

let node = {
        type: "Identifier",
        name: "foo",
        loc: {
            start: {
                line: 1,
                column: 1
            },
            end: {
                line: 1,
                column: 4
            }
        }
    };

let { loc: { start }} = node;

console.log(start.line);        // 1
console.log(start.column);      // 1

解构模式使用了花括号,表示应当下探到 node 对象的 loc 属性内部去寻找 start 属性。

每当有一个冒号在解构模式中出现,就意味着冒号之前的标识符代表需要检查的位置,而冒号右侧则是赋值的目标。 当冒号右侧存在花括号时,表示目标被嵌套在对象的更深层次中。

字符串的解构赋值

字符串被转换成了一个类似数组的对象。

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"


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

类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。

数值和布尔值的解构赋值

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。 undefinednull无法转为对象,所以对它们进行解构赋值,都会报错。

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError

函数参数的解构赋值

函数的参数也可以使用解构赋值,传入参数的时候就会被解构。

function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

参考阮一峰的ES6教程

Last updated