MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-survey

翻譯不完整。請協助 翻譯此英文文件

解構賦值語法是一種 JavaScript 運算式,可以將陣列或物件中的資料取出成獨立變數。

語法

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 3 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

預設值

變數可以被設定預設值,當在陣列對應的元素是 undefined 時會被使用。

var a, b;

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

變數交換

兩個變數可以透過一個解構指派式交換。

沒有解構指派式時,這需要一個暫存變數來達成(或者某些低階語言像是 XOR-swap trick)。

var a = 1;
var b = 3;

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

解析自函式回傳的陣列

一直以來函式都可以回傳陣列,而解構指派式可以讓回傳的值更為簡潔。

在這個例子, f() 回傳 [1, 2] ,接著透過一個解構指派式解析。

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();

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

解構一個陣列時,你可以透過其餘模式(rest pattern)將剩餘的部分指派到一個變數:

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

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

當正則運算式的方法 exec() 比對到一個值,回傳的一個陣列中第一個值是符合整個運算式的字串,其他的則是比對到括號的部分。解構指派式讓你更簡單的取出這部分,並可以忽略第一個。

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});

使用子物件表示法解構時,在指派語法外的括號——( .. )——是必要的。
* 子物件表示法原文 object literal,指以逗號分隔屬性的表示方式。

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

然而 ({a, b} = {a: 1, b: 2}) 有效,如同 var {a, b} = {a: 1, b: 2}

NOTE: Your ( ..) expression needs to be preceded by a semi-colon or it may be used to execute a function on the previous line.

指派到新的變數

變數可以從物件中提出到另一個不同名稱的變數。

var o = {p: 42, q: true};
var {p: foo, q: bar} = o;
 
console.log(foo); // 42 
console.log(bar); // true  

預設值

變數可以設定預設值,當物件中對應的值是 undefined 時使用。

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

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

Assigning to new variables names and providing default values

A property can be both 1) unpacked from an object and assigned to a variable with a different name and 2) assigned a default value in case the unpacked value is undefined.

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;
  var radius = options.radius === undefined ? 25 : options.radius;
  console.log(size, cords, radius);
  // 終於畫了東西
}

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

ES2015 version

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

drawES2015Chart({
  cords: {x: 18, y: 30},
  radius: 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.

巢狀物件或陣列的解構

var metadata = {
    title: 'Scratchpad',
    translations: [
       {
        locale: 'de',
        localization_tags: [],
        last_edit: '2014-04-14T08:43:37',
        url: '/de/docs/Tools/Scratchpad',
        title: 'JavaScript-Umgebung'
       }
    ],
    url: '/en-US/docs/Tools/Scratchpad'
};

var {title: englishTitle, translations: [{title: localeTitle}]} = metadata;

console.log(englishTitle); // "Scratchpad"
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"

這樣從 user 物件中提出了 id, displayNamefirstName 並且印出。

以物件演算屬性名稱解構

物件演算屬性名稱(像是在 object literals)可以在解構指派式使用。
(物件演算屬性名稱指——母物件["子物件名稱"]——的表示方式)

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!

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support4914411 No Yes8
Computed property names491434 No Yes No
Rest in arrays4914234 No Yes No
Rest in objects60 No55 No Yes No
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Basic support494914411 Yes8 ?
Computed property names49491434 Yes No ?
Rest in arrays494914234 Yes No ?
Rest in objects6060 No55 Yes No ?

1. Firefox provided a non-standard destructuring implementation from Firefox 2 to 40.

2. From version 14: this feature is behind the Enable experimental Javascript features preference.

參見

文件標籤與貢獻者

 此頁面的貢獻者: jackblackevo, flyinglimao
 最近更新: jackblackevo,