Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

分割代入

この翻訳は不完全です。英語から この記事を翻訳 してください。

分割代入(Destructuring assignment)構文は、配列かオブジェクトからデータを取り出して別個の変数に代入することを可能にする JavaScript の式です。

構文

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

[a, b, ...rest] = [1, 2, 3, 4, 5]
console.log(a) // 1
console.log(b) // 2
console.log(rest) // [3, 4, 5]

({a, b} = {a:1, b:2})
console.log(a) // 1
console.log(b) // 2

({a, b, ...rest} = {a:1, b:2, c:3, d:4}) //ES7 - Firefox 47a01 では未実装

説明

オブジェクトと配列リテラルは、データの ad hoc パッケージを生成する簡単な方法を提供します。

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

変数をスワップする

分割代入を使用して、複数の変数の値を入れ替えることができます。

分割代入なしで、2つの値をスワップするにはテンポラリ変数が必要です。(または、 一部の低レベルの言語では、XOR-swap trick (日本語版) があります)。

var a = 1;
var b = 3;

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

関数から返された配列を解析する

分割代入のおかげで、関数は配列を返すことができます。分割代入は、配列の戻り値を使用する作業をより簡潔にします。

この例では、f() は出力として値 [1, 2] を返しており、分割代入により 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();

正規表現のマッチから値を取り出す

正規表現 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});

代入文の周りの ( .. ) は宣言のないオブジェクトリテラル分割代入を使用するときに必要な構文です。

{a, b} = {a:1, b:2} は有効なスタンドアロンの構文ではありません。というのも、左辺の {a, b} はブロックでありオブジェクトリテラルではないと考えられるからです。

しかしながら、({a, b} = {a:1, b:2}) 形式は有効です。var {a, b} = {a:1, b:2} と考えられるためです。

新たな名称の変数に代入する

オブジェクトから変数を取り出して、オブジェクトのプロパティとは異なる名前の変数に代入することができます。

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

関数の引数のデフォルト値

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);
  // now finally do some chart drawing
}

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

ES6バージョン

function drawES6Chart({size = 'big', cords = { x: 0, y: 0 }, radius = 25} = {}) {
  console.log(size, cords, radius);
  // do some chart drawing
}

// Firefoxでは、分割代入に対するデフォルト値はまだ実装されていません (後述)。 
// 回避策は、引数を以下のように記述することです:
// ({size: size = 'big', cords: cords = { x: 0, y: 0 }, radius: radius = 25} = {})

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

Firefoxでは、分割代入に対するデフォルト値はまだ実装されていません。: var { x = 3 } = {} and var [foo = "bar"] = []. 関数内の分割代入のデフォルト値についてはバグ 932080をご覧ください。

モジュールローディング(非ES6)

分割代入はAdd-on SDKで下記のような非ES6モジュールの特定のサブセットをロードするのを助けることができます。:

const { Loader, main } = require('toolkit/loader');

The import statement in ES6 behaves similarly to destructuring, but it is important to note that it is not actually destructuring.

ネストされたオブジェクトと配列の分割代入

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

上記ではiddisplayNamefirstNameをユーザオブジェクトから引っ張りだし、プリントします。

計算されたオブジェクトのプロパティの名前と分割代入

object literalsのような計算されたプロパティの名前は分割代入で使用できます。

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

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

仕様

仕様 ステータス コメント
ECMAScript 2015 (6th Edition, ECMA-262)
Destructuring assignment の定義
標準 初期定義。
ECMAScript 2017 Draft (ECMA-262)
Destructuring assignment の定義
ドラフト  

ブラウザ実装状況

機能 Chrome Firefox (Gecko) Edge Internet Explorer Opera Safari
基本サポート 49.0 2.0 (1.8.1) 14[1] 未サポート 未サポート 7.1
計算されたプロパティの名前 49.0 34 (34) 14[1] 未サポート 未サポート 未サポート
スプレッドオペレータ 49.0 34 (34) 12[1] ? ? ?
機能 Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome for Android
基本サポート 未サポート 49.0 1.0 (1.0) 未サポート 未サポート 8 49.0
計算されたプロパティの名前 未サポート 49.0 34.0 (34) 未サポート 未サポート 未サポート 49.0
スプレッドオペレータ 未サポート 49.0 34.0 (34) ? ? ? 49.0

[1] `about:flags` で "試験的な JavaScript 機能を有効にする" の有効化が必要です。

Firefox固有のメモ

  • Firefoxは分割代入に対してJS1.7で非標準な言語拡張を提供しています。この拡張はGecko 40 (Firefox 40 / Thunderbird 40 / SeaMonkey 2.37)で削除されました。バグ 1083498をご覧ください。
  • Gecko 41 (Firefox 41 / Thunderbird 41 / SeaMonkey 2.38) より ES6 仕様に準拠するため、([a, b]) = [1, 2]({a, b}) = { a: 1, b: 2 } のように括弧でくくる分割代入は無効になり SyntaxError が発生します。詳しくは Jeff Walden のブログ記事および バグ 1146136 をご覧ください。

関連情報

ドキュメントのタグと貢献者

 このページの貢献者: lv7777, yyss, shide55
 最終更新者: lv7777,