ECMAScript6(2):解構賦值

解構賦值

解構賦值簡單來講就是 對應位置(數組)或對應鍵名(對象)的變量匹配過程。若是匹配失敗, 對於通常變量匹配不到結果就是 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
相關文章
相關標籤/搜索