2016年4月6日

[筆記] 談談JavaScript中函式的參數(parameter),arguments和展開運算子(spread)

圖片來源:Udemy

之前我們曾談過"this"這個關鍵字(註1:[筆記] 談談JavaScript中的"this"和它的bug),在這堂課中則會談到另一個JavaScript中的關鍵字,稱做"arguments"。

如同先前所述,當我們執行一個function時,一個新的execution context會被建立,接著JavaScript的引擎會替我們建立Variable Environment來保存我們的變數;然後建立Outer Environment來判斷變數的Scope Chain(註2:[筆記] JavaScript中Scope Chain和outer environment的概念);接著會產生關鍵字"this",而this的內容則會根據執行函式方式的不同而指稱到不同的物件(註3:[筆記] 談談JavaScript中的"this"和它的bug);最後還會有一個關鍵字是我們先前沒提過的,叫做"arguments"。

圖片來源:[Udemy] JavaScript: Understanding the Weird Parts

什麼是參數(parameters)


要了解arguments之前,我們必須要先了解什麼是參數(parameter)。參數其實就是我們會帶入函式的變數,以下面程式的例子來說,"phone"、"food"、"job",就是我們在執行函式的時候可以任意填入的參數。


不給任何參數值還是可以執行該函式

首先,當我建立好這樣的函式,我可以不帶任何參數值就去執行這個函式,只要輸入MyFavorite()這樣就可以了!

一般如果有參數卻又沒有給它參數值,程式的執行上往往會有錯誤!但在JavaScript中不太一樣的地方在於,即使你沒有給它任何參數值就加以執行,也不會有錯誤,而是會回傳undefined

不給任何參數值就執行。

會得到三個undefined!


為什麼會得到"undefined"呢?

之所以會這樣是因為當JavaScript在執行這個function的時候,它會先為我們的參數(phone, food, job)建立好記憶體位置,並且賦予它的值是undefined(若不清楚這個觀念可參考註4:[筆記] 談談Javascript 中的 Hoisting)。

參數值會由左至右讀取

接著,讓我們來給各個參數值,參數在給值的過程是由左至右的,什麼意思呢?

如果我依序執行這樣的程式


會分別讀到以下的結果,表示JavaScript會由左至右來讀取參數值,而且即使某些參數值有缺值的情況,JavaScript還是可以正常執行。


建立函式中參數的預設值


建立JavaScript函式中參數的預設值我們曾經在先前的文章中提過,這裡再做一次舉例說明。

直接在參數中建立預設值

由於目前多數瀏覽器使用的JavaScript版本都尚不支援直接在參數的地方建立預設值(ES6的將可以),所以很多的framework都還不會用這種方式建立預設值。

ES6的JavaScript中,可以直接透過這種方式建立參與預設值。

利用強制轉換的概念建立預設值

由於版本支援度的差異,現今多數的程式都是使用這種方式建立參數的預設值,利用簡單的"="和"||"就可以達到參數預設值的效果(之所以可以這樣使用的邏輯,可參考註5:[筆記] JavaScript中coercion的實際使用--建立函式預設值)


這時候即使在沒有給值的情況下,job一樣可以得到預設值為"developer":


什麼是arguments


瞭解了parameters的概念後,讓我們回來談談arguments。

arguments比起this來說,要容易理解的多,arguments其實就是parameters的意思,也就是說,arguments會包含所有你放入function中的參數值。

同樣地透過上面的範例加以理解,我們直接在function中去呼叫"arguments"這個關鍵字:


我們可以得到如下的結果,每一次的arguments都會分別顯示在該次函式中有哪些參數值


你會發現,arguments回傳的值是斜體的 [ ] ,看起來很像陣列(array-like),但它並不是真的陣列!所以arguments回傳的值並不具備所有陣列所具有的特徵

雖然它不是真正的陣列,但是大多數的情況下,我們還是可以把它當成陣列來使用和呼叫。例如,我們可以這樣寫,當arguments沒有任何參數的時候(arguments.length === 0),回傳訊息,並且就不要在繼續執行程式(return)。


最後,會得到如下的結果:


最後來看看展開運算子spread(...)


除了arguments這個關鍵字,在新版ES6的JavaScript中另外提供了一個展開運算子(spread),它就是「...」,這個...有什麼用呢?

根據MDN對於展開運算子spread的描述如下:

The spread operator allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) or multiple variables (for destructuring assignment) are expected.

簡單來說,就是它可以把函數中許多的參數(arguments)或陣列中許多的元素(elements)形成一個新的變數。

舉例來說:

在函式的部分,在參數的地方我們用"...other",other是你想要儲存成的變數名稱,可以自己取。

在執行程式的地方,原本我們只有三個參數(phone, food, job),也只能填寫三個參數;但使用了展開運算子"..."後,我們在執行函數的地方就可以帶入不只三個參數(例如,我在最後面又加了royale和COC),這些多的參數值最後都會被放到other這個陣列當中。


結果就會長的像這樣子:


展開運算子還有其他的使用方式,像是把陣列元素做連結等等,使用靈活的話相當方便,如果有需要的話,可以參考註6和註7。

→回到此系列文章目錄

資料來源


延伸閱讀







0 意見:

張貼留言