ES6まとめシリーズ - 変数への代入を分解する
変数の分解代入:オブジェクトの構造を分解して変数に値を代入(等号の両側のパターンが同じであることが条件
配列の分解的割り当て
配列から値を取り出し、その位置に応じて変数に値を代入します。
let [a,b,c] = [1,2,3];
 //a=1,b=2,c=3
let [ , ,c] = [1,2,3]; 
//代入cを省略する=3
let [a, [[b], c]] = [1, [[2], 3]];
//入れ子のデコンストラクション=1,c=2,c=3
let [a] = [];
//構成が成功しなかった場合、変数の値はundefinedに等しくなる。= undefined
let [x = 1 = 1] = [undefined, null];
//x = 1; j = null;
//デコンストラクションでは、デフォルト値が (===)undefined値が
//デフォルト値が式の場合、その評価は不活性である。
function f() {
 console.log('aaa');
}
let [x = f()] = [1];
//上記のコードでは、xが値を取ることができるため、関数fは全く実行されない。
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: y is not defined
デフォルト値は、分解された代入文の他の変数を参照することができるが、その変数はすでに宣言されていなければならない。
//上記の最後の式がエラーを報告する理由は、xがデフォルト値としてyを使用するとき、yがまだ宣言されていないからである。
オブジェクトの分解的割り当て
オブジェクトのプロパティに順序はなく、変数が正しい値を取るためには、プロパティと同じ名前を持つ必要があります。
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
//foo = 'aaa'; bar = 'bbb';
//変数名は属性名とは異なるので、次のように記述する。
let { foo : a, bar : b } = { foo: 'aaa', bar: 'bbb' };
//a = 'aaa'; b = 'bbb'
//foo = undefined; bar = underfined;
//オブジェクトの分解代入の内部メカニズムは、対応する変数に代入する前に、同じ名前のプロパティを見つけることである。実際に代入されるのは後者であり、前者ではない。
let { baz } = { foo: 'aaa', bar: 'bbb' };
//baz = undefined bazという名前のプロパティが見つからない
var {x: y = 3} = {};
//y = 3 デフォルト値の指定
文字列の分解的割り当て
文字列は代入のために分解することもできます。この時点で、文字列は配列のようなオブジェクトに変換されるからです。
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
配列のようなオブジェクトはlength属性を持つので、この属性への代入を分解することも可能である。
let {length : len} = 'hello';
len // 5
数値とブール値の分解的割り当て
代入を分解するとき、等号の右辺が数値とブーリアンであれば、まずオブジェクトに変換されます。
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
上記のコードでは、数値とブール値の両方のラッパー・オブジェクトがtoStringプロパティを持っているので、変数sはその値を取ることができます。
関数パラメータの分解的割り当て
function add([x, y]){
 return x + y;})
add([1, 2]; // 3
上のコードでは、add関数の引数は表向きは配列ですが、引数が渡された瞬間に配列の引数はxとyという変数に分解されます。
括弧の問題点
let x;
{x} = {x: 1};
// SyntaxError: syntax error
// 特に、中カッコが行頭にある場合、JavaScriptエンジンは{x}コードのブロックとして解釈すると構文エラーが発生する。これは、次のように括弧を追加することで解決できる。
let x;
({x} = {x: 1});
括弧は、代入文の非モーダル部分にのみ使用できる。
[(b)] = [3]; //  
({ p: (d) } = {}); //  
[(parseInt.prop)] = [3]; //  
持ち帰りポイント
- 等号の右側の値がオブジェクトや配列でない限り、まずオブジェクトに変換されます。undefinedとnullはオブジェクトに変換できないので、これらへの代入を分解するとエラーになります。
- データ構造がIteratorインターフェイスを持つ限り、配列の配列の配列、NodeListオブジェクトの配列など、配列の分解と値の割り当てに使用できます。
- オブジェクトの分解された代入は、継承されたプロパティを取ることができます。
- デフォルト値は、分解された値が厳密にundefinedに等しいという条件で有効になります。
- 括弧を使用できるのは、代入文の非モダル部分だけです。





