解構賦值簡單來講就是 對應位置(數組)或對應鍵名(對象)的變量匹配過程。若是匹配失敗, 對於通常變量匹配不到結果就是 undefined, 對於具備展開運算符(...)的變量結果就是空數組。node
var [a, b, c] = [1, 2, 3]; //a=1, b=2, c=3 var [, , c] = [1, 2, 3]; //c=3 var [x, , y] = [1, 2, 3]; //x=1, y=3 var [head, ...tail] = [1, 2, 3, 4]; //head = 1, tail = [2, 3, 4]; var [x, y, ...z] = [1]; //x=1, y=undefined, z=[]; var [a, [b, c], d] = [1, [2, 3], 4]; //a=1.b=2, c=3, d=4 var [a, [b], d] = [1, [2, 3], 4]; //a=1.b=2, d=4
數組的解構賦值能夠具備默認值, 在 ES6中對於目標數據使用嚴格相等(===)比較是否爲空(undedined)。若是默認值是表達式, 那麼對於該表達式採用惰性求值, 即只有在對應位置爲空(undedined)時才執行該表達式。數組
var [a=1, b] = []; //a=1, b=undefined var [a=1, b] = [2, 3]; //a=2, b=3 var [a=1, b] = [undefined, 3]; //a=1.b=3 var [a=1, b] = [null, 3]; //a=null, b=3 var [a=1, b] = [NaN, 3]; //a=NaN, b=3 function f(){ console.log("done"); return 2; } var [a=f()] = [1]; //a=1 var [a=f()] = []; //a=2, 輸出 "done"
解構賦值的右側表達式在必要的隱式轉換後若是不具備 iterator 則遍歷失敗, 關於 iterator, 具體看iterator部分。這裏能夠先記住, 左邊是數組結構的解構賦值, 右側能夠是數組, 字符串, 集合, Generator 函數, map等。函數
//字符串 var [a, b, c, d] = "123"; //a='1', b='2', c='3', d=undefined //集合 var [a, b, c] = new Set(['1', '2', '3']); //a='1', b='2', c='3' //Generator function* fib(){ let a = 1; let b = 1; while(1){ yield a; [a, b] = [b, a + b]; //使用結構賦值實現疊加並交換變量 } } var [a, b, c, d, e, f] = fib(); //a=1, b=1, c=2, d=3, e=5, f=8 //map var map = new Map(); map.set('a', 1); map.set('b', 2); var [a, b] = map; //a=['a', 1], b=['b', 2]
對象的解構賦值與變量位置次序無關, 只取決於鍵名是否嚴格相等(===)。若是匹配失敗, 結果就是 undefinedprototype
var {a, b, f} = {b:2, a:3, d:4}; //a=3, b=2, f=undefined var node = { loc: { start:{ x:1, y:2 } } }; var {loc: {start: {x:line}}} = node; //line=1
能夠在複製時對屬性重命名, 但此時原名只用於匹配參數, 不生成變量:code
var {name:alias} = {name:'Bob'}; //alias='Bob' console.log(name); //"global" console.log(alias); //"Bob"
對象解構一樣能夠指定默認值, 默認值生效(或表達式被行)的條件是對應屬性值嚴格等於(===) undefined對象
var {a:3, b} = {b:2}; //a=3, b=2 var {a:3, b} = {a:null, b:2}; //a=null, b=2
解構嵌套對象父屬性不存在會報錯:作用域
var {foo:{bar}} = {ba: 2}; //報錯
解構對象若是和聲明分開, 獨立成爲一行要加圓括號, 就想用 eval 解析 JSON 字符串的時候同樣。由於系統會把一行開頭花括號默認做爲塊級做用域的開始, 而不是對象的開始。字符串
var a, b; ({a, b} = {a:2, b:10}); //a=2, b=10 {a, b} = {a:2, b:10}; //報錯 //如下表達式無心義, 但沒有錯 ({}=[1, 2]); ({}="abc"); ({}=[]);
注意, 除了這樣的狀況, 不要濫用圓括號it
右側變量經過隱式類型轉換能夠轉爲對象的狀況下也能夠結構賦值:io
var {toString: s} = 123; //s=Number.prototype.toString
技巧: 解構的用處不少, 包括交換變量, 簡化傳參(可帶默認值),
//參數傳遞 function f([x, y, z=4]){ return [x+1, y+2, z+3]; } var [a, b, c] = f([1, 2]); //a=2, b=4, c=7 [[1, 2], [3, 4]].map(([a, b]) => a + b); //返回 [3, 7]
//交換變量 var a=2, b=4; [a, b] = [b, a]; //a=4, b=2