JavaScript ES6 - 解構賦值

簡單來說,解構賦值就是將右邊的值套用到左邊,通常都是在做一些物件或陣列的資料處理時會用上。
未來開發上可能會使用到類似的處理,就筆記一下唄!

前言

在開始之前,可以先試試看,如果想要將以下的陣列 family 的值,賦予到另一個變數上,該怎麼做呢?

1
let family = ['小明', '杰倫', '阿姨', '老媽', '老爸'];

我們可以宣告變數,並把值一個一個賦予。

1
2
3
let ming = family[0];
let jay = family[1];
let auntie = family[2];

除此之外,我們也可以使用 “解構賦值”,來更快地完成這件事。

“解構賦值” 基本介紹

基本 “解構賦值” 的概念,就是將右方的資料 “鏡射” 到左方。

1
2
let [ming, jay, auntie, mom, father] = family;
console.log(ming, jay, auntie, mom, father);

特性一:數量不對等

如果左右數量不對等,像是這邊只解構賦值前三個變數,那麼就會只對前三個進行解構賦值。

1
2
let [ming, jay, auntie] = family;
console.log(ming, jay, auntie);

特性二:中間缺少值

當中間值缺少,但還是有留 “逗號” 將它隔開的時候,會跳到下一個變數繼續進行解構賦值。

1
2
let [ming, jay, , mom, father] = family;
console.log(ming, jay, mom, father);

應用一:交換兩個變數

傳統上,要交換兩個變數其實滿麻煩的,通常我們會宣告一個新的第三方變數 temp,再來進行交換。

1
2
3
4
5
6
7
let Goku = '悟空';
let Ginyu = '基紐';
let temp = '';
temp = Goku;
Goku = Ginyu;
Ginyu = temp;
console.log(Goku, Ginyu); // 基紐 悟空

如果使用 “解構賦值” 來做,就不需要這麼大費周章了!
寫法是將左方的兩個變數,在右方把位置顛倒過來寫。

1
2
[Goku, Ginyu] = [Ginyu, Goku];
console.log(Goku, Ginyu);

這樣子就能完成兩個變數的交換囉!

從這個例子可以發現:
解構賦值在傳遞資料時是非常 “即時” 的,它不需要透過第三方的變數去做取代,直接就可以將兩個變數做交換。

應用二:拆解字串

我們還可以透過解構賦值的概念,拆解字串的各個字元到單一變數上。

1
2
3
let str = '基紐特攻隊';
let [q, a, z, w, s] = str;
console.log(q, a, z, w, s); // 基 紐 特 攻 隊

以上這些都是對 “陣列” 的處理方式,其實它也可以針對 “物件” 來做處理。

物件的解構賦值

透過解構賦值,我們可以從物件中取出 “其中一個值”,並賦予在新的變數名稱上。

下方範例中,左方物件裡面寫的是 “變數” 的名稱,型別為 string。

1
2
3
4
5
6
7
8
let GinyuTeam = {
Ginyu: '基紐',
Jeice: '吉斯',
burter: '巴特',
// ...
};
let { Ginyu } = GinyuTeam;
console.log(Ginyu); // 基紐

除此之外,左方變數也可以重新定義它的名稱。

寫法跟剛才很像:
首先,右方物件先被取出值,賦予到左方這個物件的屬性上,接著前方這個屬性可以再重新定義它的名稱。

1
2
let { Ginyu: Goku } = GinyuTeam;
console.log(Goku); // 基紐

類似做法:展開運算符

其實如果是要讀取物件內的 “所有” 值,並加入到單一變數上的話,也可以使用上篇筆記提到的「展開運算符」。

範例:

1
2
3
4
5
6
7
let family = {
ming: '小明',
jay: '杰倫',
};
let familyAll = { ...family };
console.log(familyAll);
// {ming: "小明", jay: "杰倫"}

延伸問題:複雜的解構

如果哪天出現了一個複雜的解構,我們首先要冷靜下來,一步一步看懂它在寫什麼。

1
2
3
4
5
let {
ming: Goku,
family: [, mom],
} = { ming: '小明', family: ['阿姨', '老媽', '老爸'] };
console.log(Goku, mom);

上面範例的答案會是什麼呢?

答案是 小明 老媽。為什麼?

麥慌啦!總之我們先從 “右邊” 開始看起。

  1. 先看右邊,我們可以看到有一個 ming 跟 一個 family
  2. 首先右方的 ming 的值,會傳到左方物件的 ming 屬性,此外它做了重新命名。
    所以,左邊這個 Goku 就是 小明 啦!
  3. 接著是 family,右方的 family 鏡射到左邊。不過,因為這個 , mom 前面有個逗點,所以它是取得第二個位置的變數,也就是 老媽 這個值。

“預設值” 的概念

下方範例中,左方的陣列裡已經有賦予值了,現在又要將後方的 ['阿明'] 賦予進去,結果會變得如何呢?

1
2
let [ming = '小明', jay = '杰倫'] = ['阿明'];
console.log(ming, jay);

結果是 阿明 杰倫,因為第一個會被賦值而取代掉,第二個會用 “預設值”。

因此,我們可以知道如果右方沒有傳值進來,左方會沿用預設值。

範例:

1
2
let { family: ming = '小明' } = {};
console.log(ming); // 小明

預設的 family 變數重新命名為 ming,並帶有預設值。
同時,因為右方沒有傳值進來,所以 ming 會繼續使用預設值,就是 小明 這個名稱。

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫。