deep-in-es6(五)
解構 Destructuring:
解構賦值允許使用類似數組或對象字面量的語法將數組和對象的屬性賦值給給中變量。
一般情況訪問數組中的前三個元素:
var first = arr[0]; var second = arr[1]; var third = arr[2];
使用解構:
var [first,second,third] = arr;
1.數組與叠代器的解構:
語法形式:var/let/const [variablel1,variablel2,variablel3,...,variablelN] = array;
var [foo,[[bar],baz] = [1,[[2],3]]; console.log(foo);//1 var [,,third] = ["foo","bar","baz"]; console.log(third);//baz //也可以通過不定參數模式獲取數組中所有尾隨的元素,依然數個數組。 var [head,...tail] = [1,2,3,4,5,6]; console.log(tail);//2,3,4,5,6
當訪問空數組或者越界訪問數組時,解構與索引的行為一致,最終得到的結果是undefined;
數組解構賦值的模式適用於任意的叠代器:
function* fibs() { var a = 0; var b = 1; while(true) { yield a; [a,b] =[b,a+b]; } } var [first,second,third,fourth,fifth,sixth] = fibs(); console.log(fifth);//5
2.對象的解構:
通過解構對象可以把對象的每個屬性與不同的變量綁定,首先指定被綁定的屬性,然後緊跟一個要解構的變量。
var robotA = { name: "alphago" }; var robotB = {name: "master"} var {name: nameA} = robotA; var {name: nameB} = robotB; console.log(nameA+" "+nameB);
屬性名與變量名一致時,可以簡寫
var {foo,bar} = {foo: "alphago",bar: "master"}; console.log(foo+" "+bar);
解構:
var obj = { arrayProp: ["Zapp",{second: "Assassin" }] }; var {arrayProp: [first,{ second }]} = obj; console.log(first);//Zapp console.log(second);//Assassin
解構一個未定義的屬性時,得到的值為undefined:
var {missing} = {}; console.log(missing);//undefined
註意:解構對象並賦值給變量時,如果沒有聲明會出現一個語法錯誤:Syntax error
{blowUp} = {blowUp:10} //Syntax error 這是因為解析引擎解析到{開始的語句會認為這是一個代碼塊是一個語句塊,解決的辦法是將整個表達式用一對小括號包裹起來。 ( {blowUp} = {blowUp:10} ); //顯示未定義的提示錯誤而非語法錯誤
解構值不是對象,數組或叠代器。
var {blowUp} = null;//TypeError: Cannot destructure property `blowUp` of ‘undefined‘ or ‘null‘.(null 沒有屬性)
當然可以解構其他原始的類型,如:布爾值,數值,字符串,但是你將會得到的是undefined:
var { whf } = NaN; console.log(whf);//undefined
默認值:
當你要解構的屬性未定義時可以提供一個默認值;
var [missing = true] = []; console.log(missing);//true var {message: msg = "Something went wrong"} = {}; console.log(msg);//Something went wrong var {x=3} = {}; console,log(x)//3
解構的實際應用:
函數參數定義:
為了設計良好的API,通常的做法是為函數世界一個對象作為參數,然後將不同的實際參數作為對象屬性,以避免讓API使用者記住多個參數的使用順序。我們可以用解構特性來避免這種問題,當我們想要引用它的其中一個屬性時,大可不必反復使用這一單以參數對象。
function removeBreakpoint({url,line,column}) { //... }
配置對象參數:
eg:
jQuery.ajax = function(url,{ async = true, beforeSend = noop, cache = true, complete = noop, crossDomain = false, global = true, //... }) { //... }
這樣我們可以避免對配置對象的每一個屬性都重復 var foo = config.foo || theDefaultFoo;這樣的操作。
與es6叠代器協議協同使用:
當我們叠代Maps(es6新加的對象),可以得到一些列如[key,value]的鍵值對,我們可以對這些鍵值對解構,跟輕松的訪問鍵和值:
var map = new Map(); map.set(window,"the global"); map.set(document,"the document"); for(var [key,value] of map) { console.log(key+"is "+value); } //[object Window]is the global //[object HTMLDocument]is the document
只遍歷鍵:
for(var [key] of map) {//...}
只遍歷值:
for(var [,value] of map) {//...}
多重返回值:
JavaScript 語言中尚未整合多重返回值的特性,但是無須多此一舉,因為我們可以返回一個數組並將結果解構:
function returnMultipleValues() { return [1,2]; } var [foo,bar] = returnMultipleValues(); console.log(foo+" "+bar);//1 2;
或者可以使用一個對象作為容器並為返回值命名:
function returnMultipleValues1() { return { foo1 : 1, bar1 : 2 } } var {foo1,bar1} = returnMultipleValues(); console.log(foo1+" "+bar1);
這兩個模式都比額外保存一個臨時變量要好得多。
function returnMultipleValues3() { return { foo2 : 1, bar2 : 2 } } var temp = returnMultipleValues3(); var fo = temp.foo2; var ba = temp.bar2; console.log(fo+" "+ba);
使用解構導入部分CommonJS模塊
我們導入CommonJS模塊X時,很可能在模塊X中道出了許多我們根本沒打算用的函數。通過解構,可以顯示定義模塊的一部分來拆分使用,同時還不會汙染我們的命名空間:
const { SourceMapConsumer, SourceNode } = require("source-map");
deep-in-es6(五)