# 解構賦值

## 語法

```var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20

[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]

({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20

// Stage 4(finished) proposal
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); // {c: 30, d: 40}
```

## 描述

`var x = [1, 2, 3, 4, 5];`

```var x = [1, 2, 3, 4, 5];
var [y, z] = x;
console.log(y); // 1
console.log(z); // 2
```

Perl 和 Python 也有類似的語法和功能。

## 陣列解構

### 基本變數指派

```var foo = ['one', 'two', 'three'];

var [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
```

### 從宣告解構指派

```var a, b;

[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2
```

### 預設值

```var a, b;

[a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7
```

### 變數交換

```var a = 1;
var b = 3;

[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1
```

### 解析自函式回傳的陣列

```function f() {
return [1, 2];
}

var a, b;
[a, b] = f();
console.log(a); // 1
console.log(b); // 2
```

### 忽略某些回傳值

```function f() {
return [1, 2, 3];
}

var [a, , b] = f();
console.log(a); // 1
console.log(b); // 3
```

```[,,] = f();
```

### 將剩餘部分解構到一個變數

```var [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]```

Note that a `SyntaxError` will be thrown if a trailing comma is used on the left-hand side with a rest element:

```var [a, ...b,] = [1, 2, 3];
// SyntaxError: rest element may not have a trailing comma```

### 從正則運算式的比對結果取值

```var url = 'https://developer.mozilla.org/en-US/Web/JavaScript';

var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)\$/.exec(url);
console.log(parsedURL); // ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript"]

var [, protocol, fullhost, fullpath] = parsedURL;

console.log(protocol); // "https"
```

## 物件解構

### 基本指派

```var o = {p: 42, q: true};
var {p, q} = o;

console.log(p); // 42
console.log(q); // true
```

### 無宣告指派

```var a, b;

({a, b} = {a:1, b:2});```

：使用物件表示解構法，而不宣告時，指派語法外的大括號 `( .. )` 是必要的。

`{a, b} = {a: 1, b: 2}` 不是有效的獨立語法，因為左邊的 `{a, b}` 被視為程式碼區塊而非物件。

`( ... )` 表達式需要冠上分號（preceded by a semicolon），否則，在上一行可能會執行之。

### 指派到新的變數

```var o = {p: 42, q: true};
var {p: foo, q: bar} = o;

console.log(foo); // 42
console.log(bar); // true  ```

### 預設值

```var {a=10, b=5} = {a: 3};

console.log(a); // 3
console.log(b); // 5```

### 指定新的變數名稱及預設值

```var {a:aa = 10, b:bb = 5} = {a: 3};

console.log(aa); // 3
console.log(bb); // 5
```

### 設定函式的預設值

#### ES5 版本

```function drawES5Chart(options) {
options = options === undefined ? {} : options;
var size = options.size === undefined ? 'big' : options.size;
var cords = options.cords === undefined ? {x: 0, y: 0} : options.cords;
// 終於畫了東西
}

drawES5Chart({
cords: {x: 18, y: 30},
});```

#### ES2015 version

```function drawES2015Chart({size = 'big', cords = {x: 0, y: 0}, radius = 25} = {}) {
// 這樣就畫了東西
}

drawES2015Chart({
cords: {x: 18, y: 30},
});```

In the function signature for `drawES2015Chart` above, the destructured left-hand side is assigned to an empty object literal on the right-hand side: `{size = 'big', cords = {x: 0, y: 0}, radius = 25} = {}`. You could have also written the function without the right-hand side assignment. However, if you leave out the right-hand side assignment, the function will look for at least one argument to be supplied when invoked, whereas in its current form, you can simply call `drawES2015Chart()` without supplying any parameters. The current design is useful if you want to be able to call the function without supplying any parameters, the other can be useful when you want to ensure an object is passed to the function.

### 巢狀物件或陣列的解構

```const metadata = {
translations: [
{
locale: 'de',
localization_tags: [],
last_edit: '2014-04-14T08:43:37',
title: 'JavaScript-Umgebung'
}
],
};

let {
title: englishTitle,// rename
translations: [
{
title: localeTitle,// rename
},
],

console.log(localeTitle);  // "JavaScript-Umgebung"```

### 循環取出的解構

```var people = [
{
name: 'Mike Smith',
family: {
mother: 'Jane Smith',
father: 'Harry Smith',
sister: 'Samantha Smith'
},
age: 35
},
{
name: 'Tom Jones',
family: {
mother: 'Norah Jones',
father: 'Richard Jones',
brother: 'Howard Jones'
},
age: 25
}
];

for (var {name: n, family: {father: f}} of people) {
console.log('Name: ' + n + ', Father: ' + f);
}

// "Name: Mike Smith, Father: Harry Smith"
// "Name: Tom Jones, Father: Richard Jones"```

### 從做為函式參數的物件中提出某屬性的值

```function userId({id}) {
return id;
}

function whois({displayName, fullName: {firstName: name}}) {
console.log(displayName + ' is ' + name);
}

var user = {
id: 42,
displayName: 'jdoe',
fullName: {
firstName: 'John',
lastName: 'Doe'
}
};

console.log('userId: ' + userId(user)); // "userId: 42"
whois(user); // "jdoe is John"```

### 以物件演算屬性名稱解構

（物件演算屬性名稱指——母物件["子物件名稱"]——的表示方式）

```let key = 'z';
let {[key]: foo} = {z: 'bar'};

console.log(foo); // "bar"
```

### Rest in Object Destructuring

The Rest/Spread Properties for ECMAScript proposal (stage 3) adds the rest syntax to destructuring. Rest properties collect the remaining own enumerable property keys that are not already picked off by the destructuring pattern.

```let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
a; // 10
b; // 20
rest; // { c: 30, d: 40 }```

### Invalid JavaScript identifier as a property name

Destructuring can be used with property names that are not valid JavaScript identifiers by providing an alternative identifer that is valid.

```const foo = { 'fizz-buzz': true };
const { 'fizz-buzz': fizzBuzz } = foo;

console.log(fizzBuzz); // "true"
```

## 規範

ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Destructuring assignment' in that specification.
Standard 初定義
ECMAScript Latest Draft (ECMA-262)
The definition of 'Destructuring assignment' in that specification.
Draft
Rest/Spread Properties for ECMAScript Draft Stage 3 draft.

## 瀏覽器相容性

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!
Update compatibility data on GitHub
Desktop Mobile Server Chrome Edge Firefox Internet Explorer Opera Safari Android webview Chrome for Android Firefox for Android Opera for Android Chrome Full support 49 Edge Full support 14 Firefox Full support 41Notes Full support 41Notes Notes Firefox provided a non-standard destructuring implementation from Firefox 2 to 40. IE No support No Opera Full support Yes Safari Full support 8 WebView Android Full support 49 Chrome Android Full support 49 Firefox Android Full support 41Notes Full support 41Notes Notes Firefox provided a non-standard destructuring implementation from Firefox 2 to 40. Opera Android Full support Yes Safari iOS Full support 8 Samsung Internet Android Full support 5.0 nodejs Full support 6.0.0 Chrome Full support 49 Edge Full support 14 Firefox Full support 41 IE No support No Opera Full support Yes Safari Full support 10 WebView Android Full support 49 Chrome Android Full support 49 Firefox Android Full support 41 Opera Android Full support Yes Safari iOS Full support 10 Samsung Internet Android Full support 5.0 nodejs Full support Yes Chrome Full support 49 Edge Full support 14Disabled Full support 14Disabled Disabled From version 14: this feature is behind the `Enable experimental Javascript features` preference. Firefox Full support 41 IE No support No Opera Full support Yes Safari No support No WebView Android Full support 49 Chrome Android Full support 49 Firefox Android Full support 41 Opera Android Full support Yes Safari iOS No support No Samsung Internet Android Full support 5.0 nodejs Full support 6.0.0 Chrome Full support 60 Edge No support No Firefox Full support 55 IE No support No Opera Full support Yes Safari Full support 11.1 WebView Android Full support 60 Chrome Android Full support 60 Firefox Android Full support 55 Opera Android Full support Yes Safari iOS Full support 11.3 Samsung Internet Android Full support 8.0 nodejs Full support 8.3.0

### Legend

Full support
Full support
No support
No support
Experimental. Expect behavior to change in the future.
Experimental. Expect behavior to change in the future.
See implementation notes.
See implementation notes.
User must explicitly enable this feature.
User must explicitly enable this feature.