Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[es6] - 变量的解构赋值 #17

Open
Jmingzi opened this issue Nov 27, 2017 · 0 comments
Open

[es6] - 变量的解构赋值 #17

Jmingzi opened this issue Nov 27, 2017 · 0 comments
Labels

Comments

@Jmingzi
Copy link
Owner

Jmingzi commented Nov 27, 2017

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

数组解构

只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。

如果等号的右边不是数组(或者严格地说,不是可遍历的结构,参见《Iterator》一章),那么将会报错。

// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

上面的语句都会报错,因为等号右边的值,要么转为对象以后不具备 Iterator 接口(前五个表达式),要么本身就不具备 Iterator 接口(最后一个表达式)。

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

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3

解构赋值允许指定默认值。

let [x = 1] = [undefined];
x // 1

let [x = 1] = [null];
x // null

// 必须严格等于undefined

默认值可以是变量,也可以是函数

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

function f() {
  console.log('aaa')
}
let [x = f()] = [1]
// 函数是不会被调用

对象的解构

最常用的解构是类似 let { log, sin, cos } = Math

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

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

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

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

// 复杂点的例子
let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};

let { p: [x, { y }] } = obj;
p // 并没有被赋值
x // "Hello"
y // "World"

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}

// 容易总结出,解构赋值从左到右,就如同变量从上到下赋值一样。
// 找到相同的key的变量,然后将这个变量的值的变量赋值操作。

// 最后一个例子加深印象
let obj = {};
let arr = [];

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

字符串的解构赋值

let { length: len } = 'abc'
// len = 3

用途

  • 交换变量的值 [x, y] = [y, x]
  • 遍历 Map 结构
  // 获取键名
for (let [key] of map) {
  // ...
}

// 获取键值
for (let [,value] of map) {
  // ...
}  
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant