此篇會介紹 JS ES6 新增的語法解構賦值的概念以及如何使用。
          
        
      
        解構賦值 Destructuring Assignment
            MDN:屬於表達式,可以將陣列、物件解構(拆解結構,Destructure),透過更簡潔的語法來取值陣列、物件到對應的變數上。
           
            解構的過程就像是鏡子映射,將右邊的值映射到左邊變數上,則沒有映射到的就是 undefined。
           
語法:
- 使用 
{}、[] 來解構,並依照解構的對象型別來選擇是 {}、[]。 
- 若無法對應到的值為 undefined。
 
e.g. 物件、陣列基礎的解構範例1 2 3 4 5 6 7 8 9 10 11 12
   | const obj = { name: 'kent' }; const arr = [20, 22];
 
  const a = arr[0]; const b = arr[1]; const name = obj.name; const age = obj.age;
 
  const [a, b] = arr  const { name, age } = obj; 
  | 
 
            下方會透過陣列、物件、函式三種的解構賦值範例來介紹其特性以及應用。
           
陣列解構

Tips
1 2
   | let [a, b, c, d] = [1, 2, 3]; console.log(a, b, c, d);     
   | 
 
- 有順序性,會依照索引值順序來對應到左邊變數上,長度不夠的索引值會自動全部忽略(因此需要透過空變數,來跳過特定陣列元素)。
 
1 2
   | let [a, b, c, d] = [1, 2, 3, 4]; console.log(a, b, c, d);   
   | 
 
1 2 3
   |  let [a, , d] = [1, 2, 3, 4]; console.log(a, d);      
 
  | 
 
注意事項
            standardJS 中有提到,絕對不要使用 ( 、 [ 或 `` 當開頭,因為會造成無法自動補上分號,一段加了 Enter 鍵(\n)後,JS 剖析器會在執行期間自動插入分號。
           
1 2 3 4
   | let a = 0 let b = 0 console.log(a, b) [a, b] = [20, 22] 
   | 
 
解決方法
1 2 3 4
   | let a = 0 let b = 0 console.log(a, b);   ;[a, b] = [20, 22]  
   | 
 
常見應用
字串拆解
1 2 3 4 5 6 7 8 9 10 11
   |  let arr = '世界和平'.split(''); let a = arr[0]; let b = arr[1]; let c = arr[2]; let d = arr[3]; console.log(a, b, c, d)      
 
  let [a, b, c, d] = '世界和平'; console.log(a, b, c, d)      
 
  | 
 
變數互換
1 2 3 4 5 6 7 8 9 10 11 12
   | let change; let name1 = 'kent'; let name2 = 'ken';
 
  change = name1; name2 = change; console.log(name1, name2); 
 
  [name1, name2] = [name2, name1]; console.log(name1, name2); 
   | 
 
物件解構

Tips
1 2
   | let { name, age } = { name: 'kent' }; console.log(name, age);   
  | 
 
- 沒有順序性,左右兩邊的數量不相等也沒問題,但無法使用空白變數(否則會噴 Error)。
 
1 2 3 4 5
   | let { age, sex } = { name: 'kent', age: 18, sex: 'M' }; console.log(age, sex);   
  let { age, ,sex } = { name: 'kent', age: 18, sex: 'M' }; console.log(age, sex);   
  | 
 
- 直接使用 {},需要在外面加上 (),否則會噴 Error 被視為區塊(block)而非物件。
 
1 2 3 4 5 6 7
   |  { age, name } = { name: 'kent', age: 20 }; console.log(name, age);   
 
  ({ age, name } = { name: 'kent', age: 20 }); console.log(name, age);   
 
  | 
 
常見應用
重複指定
1 2 3 4 5 6 7 8 9
   | let obj = { name: 'kent' };
 
  let name2 = name1 = obj; console.log(name1, name2);  
 
  let { name: name1, name: name2} = obj; console.log(name1, name2);  
  | 
 
重新賦予變數名稱
1 2 3 4 5 6 7 8 9 10
   | let obj = { name: 'kent', age: 18 };
 
  let nickName = obj.name; let age = obj.age; console.log(nickName, age); 
 
  let { name: nickName, age} = obj; console.log(nickName, age); 
  | 
 
            推測重新賦予名稱的方法,和 Object Literal 縮寫特性相關,因此原本的解構寫法應該是 { name: name } = { name: 'kent' }; 只是因為縮寫特性讓我們寫 { name } = { name: 'kent' }; 即可,想暸解更多 Object Literal 特性可以參考這篇文章。
           
快速提取 JSON 資料
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   | let JSON_data = {   id: 1237987,   name: 'kent',   age: 18,   sex: 'M',   food: {     jp: 'sushi',     us: 'fries'   }, };
 
  function getFoodOld(food) {   console.log(food); } getFoodOld(JSON_data.food);  
 
  function getFoodNew({food}) {   console.log(food); } getFoodOld(JSON_data);  
  | 
 
函式參數解構

            函式參數的用法和一般解構一樣,只是從 等號左邊解構到右邊 變為 arguments 解構到 parameters。與陣列解構、物件解構沒有太大差異這邊就不多贅述。
下方用兩個範例分別演示兩種函式參數解構的新舊寫法差異。
           
函式陣列參數解構1 2 3 4 5 6 7 8 9 10 11 12 13
   |  function fn (args) {   let month = args[0];   let day = args[1];   console.log(month, day);    } fn([11, 11]);
 
  function fn ([month, day]) {   console.log(month, day);    } fn([11, 11 ]);
 
  | 
 
函式物件參數解構1 2 3 4 5 6 7 8 9 10 11 12 13
   |  function fn (args) {   let month = args.month;   let day = args.day;   console.log(month, day);    } fn({ month: 11, day: 11 });
 
  function fn ({ month, day }) {   console.log(month, day);    } fn({ month: 11, day: 11 });
 
  | 
 
            介紹到這邊對於解構賦值基礎運用已具備一定程度的理解,下方會介紹幾種稍微進階一咪咪的解構賦值應用。
           
非基礎應用
設定默認值(預設值)
- 防止出現 undefined 結果,再解構變數後方使用 = 並賦予一個值。
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | const obj = { name: 'kent' }; const arr = [20, 22];
 
  const [a, b, c = 1] = arr; console.log(a, b, c);   
 
  const { name, age = 18 } = obj; console.log(name, age); 
 
  function fn ([a, b, c = 1]) {   console.log(a, b, c);    } fn(arr);
  | 
 
1 2 3 4 5 6 7 8 9 10 11
   |  function fn ([a, b, c = 1]) {   console.log(a, b, c);    } fn();
 
  function fn ([a, b, c = 1] = []) {   console.log(a, b, c);    } fn(); 
 
  | 
 
巢狀解構

1 2 3 4 5 6 7
   |  let { name: boy, name: [men] } = { name: ['kent'], age: 18 }; console.log(boy, men);  
 
  let { info, info: {name} } = { info: {name: 'kent', age: 18} }; console.log(info, name);  
 
  | 
 
巢狀預設值
- 對於需要依照不同情況組合不同參數非常方便(例如:config 參數)。
 
src:你懂 JavaScript 嗎?#29 語法(Syntax)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   | let defaults = {   setupFiles: ['setup.js', 'setUp-another.js'],   testUrl: 'https://sample.com.tw',   support: {     a: true,     b: false,   }, };
  let config = {   testUrl: 'https://sample-special.com.tw',   support: {     a: false,     c: true,   }, };
  let dev_config = {   setupFiles = defaults.setupFiles,   testUrl = defaults.testUrl,   support = defaults.support, } = config;
  console.log(dev_config);
  | 
 
展開運算子、其餘運算子
- 這邊範例只會展示和解構相關,若想暸解關於展開運算子、其餘運算子可以參考這篇文章。
 
展開運算子(組合資料)1 2 3 4 5 6 7 8 9 10 11
   |  let [a, ...b] = ['世', '界', '和', '平'];  console.log(a, b); 
 
  const [a, ...b] = ['世']; console.log(a, b); 
 
  let { name, ...info } = { name: 'kent', age: 18, sex: 'M'}; console.log(name, info); 
 
  | 
 
e.g. 其餘參數(拆解資料)1 2 3 4 5 6
   | function fn(...[a, b, c, d]) {   console.log(a, b, c, d); }
  fn('世');  fn('世', '界', '和', '平');  
  | 
 
reference