# [Javascript] ES6 Spread Syntax 展開語法

# Spread Syntax 表示。

在自然用語中,我們會使用 作為一種表示「剩下的、其他」的意思。

在 Javascript ES6 中,納入了這種 三個點(...) 的用法。可以很輕鬆的表示 Array 中 「剩下的」Elements,或是 call function 時給予 「其他的」parameters。

Spread Syntax 允許在創建 Array 時,將一個 Array、或 string 在語法層面展開 (expand) 其內容成為個別數值 (Value);還可以在 創建 Object 時,將來源 Object 按照 key-value 的方式展開;或是在 function call 時對傳入參數、接收參數進行展開」的速寫語法 — MDN doc

講起來很饒口,我們直接來看幾個例子會更快瞭解。

# 將 array array1 的內容展開給 array2

以往我們要將 array2 的內容擴展給 array1 要不就是用迴圈一個一個倒過去 (例如下面例子)

var array1 = [1, 2, 3, 4];
var array2 = [5, 6, 7, 8];
array2.forEach( num => array1.push(num) )

不然就是用 Array.concat() (例如下面例子)

var array1 = [1, 2, 3, 4];
var array2 = [5, 6, 7, 8];
array1 = array1.concat(array2)

如今,有了使用 Spread Operator 我們就可以很優雅的表示這個過程。

/** spread array example */
var array1 = [1, 2, 3, 4];
var array2 = [5, 6, 7, 8];
array2 = [ ...array1, ...array2 ] // [1, 2, 3, 4, 5, 6, 7, 8]

# string str1 的內容展開給 result_ary

由於 Javascript 可以將 string 視作 character array 般巡行 (類似 C 中的字元陣列),因此我們利用此特性將 string 展開成 array。

/** spread array example */
var str1 = "hello";
var result_ary = [...str1] // ["h", "e", "l", "l", "o"]

# 將 Object object1 的內容展開給 object2

除了 Array 的擴展之外我們也可以使用在 Object 上。以往我們在將 object1 的內容給 object2 時,如同 array 的做法,不是使用迴圈一個一個 assign (如下面例子)

var object1 = {"a": 1, "b": 2, "c": 3, "d": 4};
var object2 = {"e": 5, "f": 6, "g": 7, "h": 8};
for ( let key in object1 ) {
    // 將 object1 的內容在 object2 中創建
    object2[key] = object1[key];
}

不然就是使用 Object.assign (如下面例子)

var object1 = {"a": 1, "b": 2, "c": 3, "d": 4};
var object2 = {"e": 5, "f": 6, "g": 7, "h": 8};
Object.assign(object2, object1);

Object 方面,我們也可以使用 Spread Syntax 優雅地完成以前需要大費周章才能達成的目標

var object1 = {"a": 1, "b": 2, "c": 3, "d": 4};
var object2 = {"e": 5, "f": 6, "g": 7, "h": 8};
// 將 object1, 跟 object2 展開成新的 object 給 object2
object2 = {...object1, ...object2};

這邊要注意的是,若是 object2 中有 key 是與 object1 相同的話,輸出的內容可能會因為 object2 較晚展開,而覆蓋 object1 對於此 key 所設定的內容。

# 在 Function parameters 中使用 Spread Syntax

Javascript 是一個很靈活的程式語言,他可以允許動態數量的參數內容。

因此我們可以在定義參數時利用 Spread Syntax 來表示 「剩下要傳入的參數們」 這種概念。

以下方這個 加法 function 為例,平常我們只想做兩個數值的相加,但是利用 Spread Syntax 我們可以做到兩個以上數值的相加。

var add = (a, b, ...others) => {
    if (!others) return a + b;
    return a + b + others.reduce( (total, current) => current + total, 0 )
}
console.log( add(1, 2) ) // 3
console.log( add(1, 2, 3) ) // 6
console.log( add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) )  // 55

在上面的 code 中, others 會將剩下傳入的參數 「全部接收」 ,變成一個 array,因此當我們使用 add(1, 2, 3, 4) 時,其實 others 得到的會是 [1, 2, 3, 4] 這樣的結構。

如此寫法的好處在於其 大大簡化了獲取多餘參數的寫法。

以往我們可能需要利用 arguments.length 判斷參數數量,並且手動切出額外的參數才能進行相應的動作,如今有了 Spread Syntax 後我們便不需要進行如此繁瑣的事項了。

以往我們可能需要這樣寫

var func1 = ( param1 ) => {
    var params = Array.prototype.slice.call( arguments );
    var opts = params.splice(1, params.length-1); // 從第一格開始切到最後一個參數
    console.log("param1", param1, "opts", opts);
    if (opts.length == 1) { console.log( "do something ... only 1 opts" )}
    else if (opts.length == 2) { console.log( "do things that has 2 opts" )}
    else if (opts.length == 3) { console.log( "do things that has 3 opts" )}
    else { console.log( "do else " )}
}

如今上面的程式我們可以改成

var func1 = ( param1, opts ) => {
    console.log("param1", param1, "opts", opts);
    if (opts.length == 1) { console.log( "do something ... only 1 opts" )}
    else if (opts.length == 2) { console.log( "do things that has 2 opts" )}
    else if (opts.length == 3) { console.log( "do things that has 3 opts" )}
    else { console.log( "do else " )}
}

# 利用 Spread Syntax 於傳參時展開傳入的參數

我們能在 Function 定義參數時使用 Spread Syntax ,當然也能在 Function call 時使用。

假定有一個 function 如下表示,接收 4 個參數。

function func1(a, b, c, d) {
    console.log("a:", a, ", b:", b, ", c:", c, ", d:", d)
}

我們以往需要 value by value 地傳入各自的數值:

func1(1, 2, 3, 4) // a:1, b:2, c:3, d:4

如今可以利用 Spread Syntax 將 array 傳入時自動展開,會得到如上相同的效果。

func1(...[1, 2, 3, 4]) // a:1, b:2, c:3, d:4

要注意的是,若是 array 中的 elements 數量多於 function 接收的參數數量, a, b, c, d 依然只會吃到 1, 2, 3, 4 。array 剩下的內容要從 arguments 去獲取喔!

例如下面的例子:

function func1(a, b, c, d) {
    console.log("a:", a, "b:", b, "c:", c, "d:", d);
    console.log("params", Array.prototype.slice.call( arguments ))
}

# 結論

其實 Spread Syntax 就是一個語法糖,不了解基本上也不會怎麼樣。但是多學到一種寫法,可以讓我們的程式碼更加優美,何樂而不為呢?

如果這篇對你有幫助,請不要吝情於給我一點鼓勵。

Like z20240z's work