一.目標
オブジェクトまたは配列から値を取得し、他の変数に代入するには、以前はこのようにする必要がありました:
var arr = [1, 2, 3, 4];
var first = arr[0];
var senond = arr[1];
var third = arr[3];
配列を分解して要素値を取得し、代入します。上記のプロセスは:分解 - 代入です
ES6 は新しい概念を提案しました:destructuring(分割代入)、上記のプロセスをより良い可読性を持たせ、「ハードコーディング」スタイルのコードを回避できます
二.iterable 分割代入
var/let/const [var1, var2...] = iterable 構文は、変数宣言と同時に配列/イテレータ分割代入を行うことを表します
分割される値は iterable でなければなりません。ジェネレーター構文を通じてカスタムオブジェクトを簡単に iterable にできます([黯羽軽揚:for…of ループ_ES6 ノート 1](/articles/for-of 循环-es6 笔记 1/#articleHeader5) を参照)。iterable 分割代入の特徴は以下の通り:
-
任意の深さのネスト配列に対して分割代入可能
-
空位を残して特定の要素をスキップ可能
-
可変長引数(
...var構文、詳細は [黯羽軽揚:デフォルトパラメータと可変長引数_ES6 ノート 4](/articles/默认参数和不定参数-es6 笔记 4/) を参照)を使用して残りのすべての要素をキャプチャ可能
例えば:
// 配列
var [[first, [second]], third] = [[1, [2]], 4];
console.log(`first = ${first}`); // 1
console.log(`second = ${second}`); // 2
console.log(`third = ${third}`); // 4
// iterable
var iter = (function*(start) {
while (true) {
yield start++;
}
})(0);
var [v1, v2, v3, v4] = iter;
console.log(`v1 = ${v1}`); // 0
console.log(`v2 = ${v2}`); // 1
console.log(`v3 = ${v3}`); // 2
console.log(`v4 = ${v4}`); // 3
// 要素をスキップ、残りの要素をキャプチャ
var arr = [1, 2, 3, 4];
var [, sec, ...aRest] = arr;
console.log(`sec = ${sec}`); // 2
console.log(`aRest = ${aRest}`); // [3, 4]
「ハードコーディング」スタイルのコードはすべてなくなり、しかも分割代入はより明確で直感的です(左右対応)
三.オブジェクト分割代入
var/let/const {key: varName, ...} = obj 構文はオブジェクト分割代入を表します
特に注意:代入順序は左から右へ です。実際の効果は:varName = obj[key] です
分割される値は必ず オブジェクトに強制変換できる必要があります。そのため undefined/null を分割代入すると TypeError が報告されます
オブジェクト分割代入の特徴は以下の通り:
-
変数名とオブジェクトプロパティ名が一致する場合は簡略化可能
-
特定のプロパティ名に対してのみ代入可能(空位を残してスキップする必要はありません)
-
複雑なネスト(オブジェクト + 配列)をサポート
例えば:
// obj
var obj = {name: 'aae', age: 12, sex: 'F'};
// 特定のプロパティ名に対してのみ代入
var {name: mName, sex: mSex} = obj;
console.log(`mName = ${mName}`); // mName = aae
console.log(`mSex = ${mSex}`); // mSex = F
// 変数名とプロパティ名が同じ場合簡略化
var {name, sex} = obj;
console.log(`name = ${name}`); // name = aae
console.log(`sex = ${sex}`); // sex = F
注意、分割代入の左側に var/let/const がない場合(つまり変数宣言を忘れたか、変数がすでにあり再宣言したくない)、構文エラーが発生します。以下の通り:
// var key;
{key} = {key: 'val'};
// 报错:Uncaught SyntaxError: Unexpected token =(…)
代入記号の左側の {key} はブロック({})として解析されるためです。この動作を回避する方案は分割代入に丸括弧を付ける ことです。例えば:
({key} = {key: 'val'});
console.log(`key = ${key}`); // key = val
丸括弧 inside はすべて式であり、{key} は誤ってブロックとして解析されません
四.分割代入同時にデフォルト値を設定
構文はデフォルトパラメータ構文と類似です。例えば:
// default val
var [val = 'default val'] = [];
var {key: val = 'default val'} = {};
// 属性名が同じ場合簡略化可能
// FF43,45 都不支持,thinkjs,Chrome50 支持
// var {val = 'default val'} = {};
console.log(`val = ${val}`);
1 つの文でデフォルト値を設定し、分割代入も行いますが、構文はより複雑な場合で読みづらいです(例えば上記の var {key: val = 'default val'} = {};)
五.まとめ
この特性も錦上添花的なもので、「ハードコーディング」スタイルのコードを減少し、その可読性を強化します
用途:
-
関数定義中のオブジェクト��ラメータ、例えば
function ajax(config)、function ajax({url, data, callback})に変更後 API 可読性がより良く、デフォルト値と配合して非常に便利です(var attr = config.attr || defultVal;のような操作を回避) -
イテレータと配合し、map を遍历するのに便利です([key, val] 遍历鍵値対、[key] 遍历鍵集、[, val] 遍历値集)
-
関数が複数の値を返すことを実装(配列を返し、戻り値を受け取る時に各変数に分割代入)
-
一部の CommonJS モジュールをインポートし、必要な部分のみ分割代入。ES6 モジュールの import は類似の機能をサポート
例えば:
// use
// 1
function ajax({url, data, callback}) {
console.log(`ajax(${url}, ${data}, ${callback})`);
}
ajax({url: 'www.xxx.xx', data: 'data'});
// log print: ajax(www.xxx.xx, data, undefined)
// 2
for (var [key, val] of new Map([['name', 'eea'], ['age', 12]])) {
console.log(`key = ${key}, val = ${val}`);
}
// log print: key = name, val = eea
// key = age, val = 12
// 3
var [res1, res2] = (function() {
return [1, {a: 1}];
})();
console.log(`res1 = ${res1}, res2 = ${res2}`);
// res1 = 1, res2 = [object Object]
参考資料
- 《ES6 in Depth》:InfoQ 中国語駅が提供する無料電子書籍
コメントはまだありません