話說,解構無處不在啊,鄙人自從用了vue寫項目以來,總是遇到各路大神莫名其妙的寫法,然並未出任何錯,查之,然解構也,嗚呼哀哉,進而習之。
解構(Destructuring):是將一個數據結構分解為更小的部分的過程。ES6中,從數組和對象中提取值,對變量進行賦值。
解構有什么用處呢?可以大大的簡化數組或者對象里面的元素的賦值語句。
數組解構,數組本身並沒有發生任何的改變,解構是對新的變量(可能是對象同名屬性)賦值。
//變量的聲明 let [a,b,c] = [1,2,3];
//嵌套解構 let [foo,[bar],baz] = [1,[2],3];
//類似函數的剩余參數,數組解構有個類似的,剩余項的概念。 ...tail,里面的tail就是剩余項,也是個數組 let [head,...tail] = [1,2,3,4]; //head:1,tail:[2,3,4] let [x,y,z] = new Set(['a','b','c']); //解構允許指定默認值 let [foo = true] = []; //foo:true let [x,y='b'] = ['a']; //x = 'a',y = 'b'
如果你只想獲取數組中的第三個元素,則不必給前兩項提供變量名。栗子如下:
let colors = ["red","green","blue"]; let [,,thirdColor] = colors; console.log(thirdColor) //blue
JS中有個被遺漏的功能:克隆數組,ES5中用concat,用來合並數組,如果不傳遞任何參數,就是原數組的克隆品。ES6中可以使用剩余項達到同樣的效果:
let colors = ["red","green","blue"]; let [...cloneColors] = colors; console.log(cloneColors) //["red", "green", "blue"]
本例中剩余項將colors數組的值復制到cloneColors數組中,這個技巧值的關注。。。剩余項是數組解構模式中最后一項,后面不能有逗號。。。
對象的解構:
let {foo,bar} = {foo:"aaa",bar:"bbb"}; //實例舉例,下面的變量x就是1,y是2,c為定義是is no defined var obj = {x:1,y:2,c:1}; let {x,y} = obj; let { baz } = { foo: "aaa", bar: "bbb" }; baz // undefined
//如果對象的屬性已被變量賦值,再次賦值時候需要用圓括號括起來,因為花括號里面並不是塊語句,而是解構賦值表達式。
let node = {
type:'Identifier',
對象的解構變量必須與屬性同名,才能取到爭取的值。而且對象的屬性是沒有次序的,而數組的元素是按次序排列的。如果想要變量名和屬性名不一致,那么必須這樣寫:
let {foo:baz,hand:lochand = 'eart'} = { foo: "aaa", bar: "bbb" }; baz //'aaa',此時的foo就是未定被定義的,定義的變量只有baz
lochand //'eart' 此時的hand雖然undefined,但是lochand有被初始化 let {foo:foo,bar:bar} = {foo:"aaa",bar:"bbb"}
實際上也說明,對象的解構賦值是內部機制,先找回同名屬性,再賦值給對應的變量,真正被賦值的是后者。現在已經掌握了如何對屬性值為基本類型值的對象進行解構,而對象解構也可被用於從嵌套的對象結構中提取屬性值。(嵌套對象表示:對象的屬性可能還是一個對象)舉個例子:
let node = { type:'Identifier', name:'foo', loc:{ start:{ line:1, column:1 }, end:{ line:1, column:4 } } }; let {loc:{start}} = node;
console.log(start) //{line: 1, column: 1}、
let {loc:{start:localStart}} = node;
console.log(localStart) //{line: 1, column: 1}
嵌套對象的模式,里面使用了{},表示在node對象的loc屬性內部尋找start屬性。每當有個冒號在結構模式中出現,冒號之前的標識符代表需要檢查的位置,冒號右側則是賦值的目標;當冒號右側存在花括號時,表示目標被嵌套在對象的更深層次中。
在對象的嵌套解構中也是可以給本地變量使用不同的名稱,看上面的栗子(node.loc.start的值被存儲在一個新的本地變量localStart上):
混合解構:
對象和數組解構能被組合使用,以創建更復雜的解構表達式。栗子如下:
let node = { type:'Identifier', name:'foo', loc:{ start:{ line:1, column:1 }, end:{ line:1, column:4 } }, range:[0,3] }; let { loc:{start}, range:[startIndex] } = node; console.log(start,startIndex); //{line: 1, column: 1} 0
上面的代碼提取出node.loc.start和node.range[0],並將它們的值分別存儲在start和startIndex上。
參數解構:
解構還有一個很有用的場景,在傳遞函數參數時,當JS函數接收大量可選參數時,一種常用模式是創建一個包含附加參數的options對象:
function setCookie(name,value,options){ options = options || {}; let secure = options.secure, path = options.path, domain = options.domain; } setCookie("type","js",{ secure:true, path:'http://baidu.com' })
name和value參數是必需的,而options中的secure,path等是可選的。參數解構提供了更清楚標明函數期望輸入的替代方案。用對象或數組解構的模式替代了具名參數。看上面的栗子,解構參數在未傳遞值的情況下會被設定為undefined,類似於常規參數。
圓括號和解構賦值的關系:
只要有可能導致解構歧義,就不得不使用圓括號。
let x = 2; ({x} = {x:1});
console.log(x) //1 //對象的解構賦值可很方便的將現有對象的方法,賦值到某個變量 let {log,sin,cos} = Math; //由於數組本質是特殊的對象,因此可以對數組進行對象屬性的解構 let arr = [1,2,3]; let {0:first,[arr.length-1]:last} = arr; first //1 last //3
對於字符串,數字,布爾值的解構賦值規則:只要等號右邊的值不是對象或者數組,就先將其轉化為對象,undefined和null是無法轉化為對象,所以對它們進行解構賦值會報錯。
[[1,2],[3,4]].map(([a,b]) => a+b) //[3, 7]
對於函數的解構賦值,可以將形參以數組的形式傳入,如上,數組參數被解構成變量a和b,對於函數內部就只是參數a,b。
用途:
1,變量交換:看起來如同鏡像。賦值語句的左側的解構模式,右側是臨時創建的數組字面量。x被賦值為數組中的y,y被賦值為數組中的x。
let x = 1; let y = 2; [x,y] = [y,x]
2,函數返回多個值
function example(){return [1,2,3]} let [a,b,c] = example(); function example(){return {foo:1,bar:2}} let {foo,bar} = example();
3,函數參數的定義
解構賦值可以方便的將參數和變量名對應起來,可以無次序
function f({x,y,z}){...} f({z:2,y:8:x:9})
4,提取JSON數據,有關json的提取就是對象的解構賦值而已。
5,函數參數的默認值
指定參數的默認值,就避免了在函數體內再寫 || 語句。
jQuery.ajax = function(url,{ async = true, beforeSend = function(){}, cache = true, complete = function(){}, crossDomain = false, global = true, } = {}){ }
//這種寫法有個缺點,當傳入參數值為null時會引發程序異常。因為null和undefined是無法被解構的。
6,輸入模塊的指定方法
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
關鍵字:【對象】【數組】【參數解構】
古今之成大事業,大學問者,必經過三種之境界:“昨夜西風凋碧樹。獨上高樓,望盡天涯路。”此第一境也。“衣帶漸寬終不悔,為伊消得人憔悴。”此第二境也。“眾里尋他千百度,驀然回首,那人卻在燈火闌珊處。”此第三境也。 ——王國維《人間詞話》