# 解構賦值

## 語法

```let 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}
```

## 描述

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

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

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

## 陣列解構

### 基本變數指定敘述

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

const [red, yellow, green] = foo;
console.log(red); // "one"
console.log(yellow); // "two"
console.log(green); // "three"
```

### 宣告指派分開敍述

```let a, b;

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

### 預設值

```let a, b;

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

### 變數交換

```let a = 1;
let b = 3;

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

const arr = [1,2,3];
[arr[2], arr[1]] = [arr[1], arr[2]];
console.log(arr); // [1,3,2]

```

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

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

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

### 忽略某些回傳值

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

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

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

### 把矩陣剩餘部分解構到一個變數

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

```const [a, ...b,] = [1, 2, 3];

// SyntaxError 語法錯誤: 其餘元素不可以跟隨結尾逗號
// 需要把其餘運算子放在最後的元素
```

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

```function parseProtocol(url) {
const parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)\$/.exec(url);
if (!parsedURL) {
return false;
}
console.log(parsedURL); // ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript"]

const [, protocol, fullhost, fullpath] = parsedURL;
return protocol;
}

console.log(parseProtocol('https://developer.mozilla.org/en-US/Web/JavaScript')); // "https"
```

## 物件解構

### 基本指派式

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

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

### 無宣告指派

```let a, b;

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

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

`( ... )` 表達式前句需要以分號結束，否則可能把上一句視為函式隨即執行。

### 指派到新的變數名稱

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

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

### 預設值

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

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

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

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

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

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

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

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

function whois({displayName, fullName: {firstName: name}}) {
return `\${displayName} is \${name}`;
}

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

### 設定函式參數的預設值

```function drawChart({size = 'big', coords = {x: 0, y: 0}, radius = 25} = {}) {
// do some chart drawing
}

drawChart({
coords: {x: 18, y: 30},
});```

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

```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"```

### 循環取出的解構

```const 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 (const {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"
```

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

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

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

### 在物件解構時使用其餘變數

ECMAScript 中的其餘/展開屬性在 proposal (stage 4) 新增了在解構式內使用其餘 (rest) 語法的定義。其餘屬性可以收集解構式中沒有指定的屬性值。

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

### 不符合 JavaScript 識別字的屬性名稱

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

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

### 混合使用矩陣及物件解構

```const props = [
{ id: 1, name: 'Fizz'},
{ id: 2, name: 'Buzz'},
{ id: 3, name: 'FizzBuzz'}
];

const [,, { name }] = props;

console.log(name); // "FizzBuzz"
```

### 物件解構時的原型鏈追溯

```let obj = {self: '123'};
obj.__proto__.prot = '456';
const {self, prot} = obj;
// self "123"

## 瀏覽器相容性

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 36 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 36 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 36 Safari Full support 10 WebView Android Full support 49 Chrome Android Full support 49 Firefox Android Full support 41 Opera Android Full support 36 Safari iOS Full support 10 Samsung Internet Android Full support 5.0 nodejs Full support 6.0.0 Chrome Full support 49 Edge Full support 16 Full support 16 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 36 Safari Full support 9.1 WebView Android Full support 49 Chrome Android Full support 49 Firefox Android Full support 41 Opera Android Full support 36 Safari iOS Full support 9.3 Samsung Internet Android Full support 5.0 nodejs Full support 6.0.0 Chrome Full support 60 Edge Full support 79 Firefox Full support 55 IE No support No Opera Full support 47 Safari Full support 11.1 WebView Android Full support 60 Chrome Android Full support 60 Firefox Android Full support 55 Opera Android Full support 44 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.