##一。目標
從物件或者陣列裡取值並賦值給其它變數,以前得這樣做:
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
圓括號裡面的都是表示式,{key} 不會被誤解析為塊
##四。解構同時設定預設值
語法與預設引數語法類似,例如:
// default val
var [val = 'default val'] = [];
var {key: val = 'default val'} = {};
// 屬性名相同時可以簡寫為
// FF43,45 都不支援,thinkjs,Chrome50 支援
// var {val = 'default val'} = {};
console.log(`val = ${val}`);
一條語句既設定預設值,又解構賦值,但語法在更複雜的情況下語法有些難讀(例如上面的 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 中文站提供的免費電子書
暫無評論,快來發表你的看法吧