此篇會介紹 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