ECMAScript 2015 提供了很有創意的 Array Destructuring,原本需要好幾行才能完成的寫法,最後只需一行就能解決。
Version
macOS Mojave 10.14.5
VS Code 1.41.1
Quokka 1.0.267
ECMAScript 2015
Basic Assignment
let data = [1, 2, 3]
let x = data[0]
let y = data[1]
let z = data[2]
x // ?
y // ?
z // ?
data
為 array,想分別指定到 x
、y
與 z
3 個 variable,ES5 必須寫 3 行。
let data = [1, 2, 3]
let [x, y, z] = data
x // ?
y // ?
z // ?
將 x
、y
與 z
直接寫在 []
內,array 會依照順序直接分解到 variable,ES6 只需 1 行。
Batch Assignment
let x = 1
let y = 2
x // ?
y // ?
若要對多個單一 variable 指定 value,ES5 有幾個 variable 就要寫幾行。
let [x, y] = [1, 2]
x // ?
y // ?
可將所有 variable 與 value 都用 array 整理起來,ES6 只要一行即可搞定。
Swap Variable
let x = 1
let y = 2
let temp = x
x = y
y = temp
x // ?
y // ?
若要兩個 variable 內容交換,ES5 會另外建立 temp
暫存變數,需要 3 行。
let x = 1
let y = 2;
[y, x] = [x, y]
x // ?
y // ?
ES6 將 variable 寫在 []
直接交換,只要 1 行,可讀性非常高。
Extract Array
let data = []
let name = 'Sam'
if (data.length > 0)
name = data[0]
name // ?
ES5 若想將 array 內 element 指定為 variable,但又不確定 array 是否有該 element,傳統會先對 variable 指定 default value,並檢查 array 的 length
property,若確定 length
如預期,再使用 index
存取 array 指定給 variable。
let data = []
let [name = 'Sam'] = data
name // ?
ES6 可直接在 array destructuring 時指定 default value,不需再搭配 if
判斷。
let data = ['John', 'Kevin']
let [_, _, name = 'Sam'] = data
name // ?
若要分解的 variable 不是第一個 element 也沒關係,只要使用 ,
留出空位即可,_
並非必須,但有助於可讀性,亦可同時指定 default value。
Clone Array
let data0 = [1, 2, 3]
let data1 = data0
data1 // ?
data0 === data1 // ?
若要複製 array,直覺會使用 =
,但 array 並非 primitive,而是 object,因此只是複製記憶體位置,所以 data0
與 data1
仍然指向同一個 [1, 2, 3]
,而不是真的 clone array。
let data0 = [1, 2, 3]
let data1 = data0.slice()
data1 // ?
data0 === data1 // ?
ES5 可使用 Array.prototype.slice()
將 array 加以複製,slice()
是真的回傳一個新 array,而非指向同一個 array。
let data0 = [1, 2, 3]
let data1 = data0.concat()
data1 // ?
data0 === data1 // ?
ES5 也可以使用 Array.prototype.concat()
複製一個新 array,與 slice()
結果相同。
let data0 = [1, 2, 3]
let [...data1] = data0;
data1; // ?
data0 === data1; // ?
ES6 則有新的寫法,array destructuring 配合 ...
spread operator,其結果等同於 ES5 的 slice()
與 concat()
。
let data0 = [1, 2, 3]
let data1 = [...data0]
data1 // ?
data0 === data1 // ?
亦可將 ...
寫在右側展開亦可。
let data0 = [1, 2, 3]
let [_,...data1] = data0
data1 // ?
若要 clone 的只是部分 array,可使用 ,
空出 space 即可。
Extract Character
let str = 'Chinese'
let [firstChar] = str
firstChar // ?
Destructuring 除了可以用在 array 外,事實上也能用在 iterable,最簡單的 iterable 就是 string,可用來將 string 中特定 char 指定到 variable。
let str = 'Chinese'
let [_, secondChar] = str
secondChar // ?
若要分解的 variable 不是第一個 index 也沒關係,只要使用 ,
留出空位即可。
Function Parameter
let data = [1, 2, 3]
let fn = function(args) {
let a = args[0]
let b = args[1]
let c = args[2]
console.log(a, b, c)
}
fn(data)
若 parameter 為 array,ES5 會使用 array index 一一的指定給 variable,需要 3 行。
let data = [1, 2, 3]
let fn = ([a, b, c]) => console.log(a, b, c)
fn(data)
ES6 可在 parameter 使用 array destructuring 直接將 array 分解成 variable。
雖然只是一個 array,但若使用 arrow function 時,仍須加上 ()
將 array 刮起來。
let data = [1, 2, 3]
let fn = ([a, b, c, d = 4]) => console.log(a, b, c, d)
fn(data)
若想提供 default value 也行,使用 =
提供 default value 即可。
let data = ['RGB', [255, 0, 255]]
let fn = function(args) {
let name = args[0]
let red = args[1][0]
let green = args[1][1]
let blue = args[1][2]
console.log(name, red, green, blue);
}
fn(data)
若 parameter 是 nested array,在 ES5 必須一一分解 variable,需要 4 行。
let data = ['RGB', [255, 0, 255]]
let fn = ([name, [red, green, blue]]) => console.log(name, red, green, blue)
fn(data)
ES6 也可直接在 parameter 分解 nested array。
Function Return Array
let fn = function() {
return [1, 2, 3]
}
let result = fn()
let a = result[0]
let b = result[1]
let c = result[2]
a // ?
b // ?
c // ?
若要讓 function 回傳多值,在 ES5 正規解法就是回傳 array,呼叫端接到 array 後,再使用 array index 一一指定給 variable,需要多行。
let fn = () => [1, 2, 3]
let [a, b, c] = fn()
a // ?
b // ?
c // ?
在 ES6 可使用 array destructuring 接收 function 回傳的 array,並自動分解成 variable,只需 1 行。
let fn = () => [1, 2, 3]
let [a, _, c] = fn()
a // ?
c // ?
若並不想分解 function 所傳回所有 array,可以在 ,
與 ,
之間空著,會自行忽略分解之。
let fn = () => [1, 2, 3]
let [a, ...c] = fn()
a // ?
c // ?
若 function 回傳的 array,想部分也分解成 array,可搭配 ...
spread operator。
但這種寫法必須寫在 array destructuring 的最後才行
Conclusion
- Array destructuring 的基本精神就是
一個蘿蔔一個坑
,ES6 會自動將 array 分解成 variable - 若要同時將多值給不同 variable,可將所有 variable 與 value 都用 array 整理起來,只要一行即可
- Swap variable 算是 array destructuring 很巧妙的應用
- Array destructuring 配合 spread operator,可以取代原本
slice()
與concat()
才能 clone array - 事實上只要是 iterable 就能使用 destructuring,而 string 就是最簡單的 iterable,因此也能使用 destructuring
- Array destructuring 配合 function parameter 特別好用,可以直接在 parameter 中就分解成 variable,還可搭配 default value
- Array destructuring 可將 function 回傳的 array 直接分解到 variable
Reference
MDN, Destructuring assignment
Glad Chinda, ES6 Destructuring: The Complete Guide
Liam Hurst, 5 Interesting Uses of JavaScript Destructuring