JavaScript ES6 - 箭頭函式與傳統函式的差異
箭頭函式其實有一些陷阱,大部分情況下使用傳統函式其實就夠用了。
將傳統函式改寫成 “箭頭函式”
下方範例是我們一般傳統函式的寫法:
1 | var callSomeone = function (someone) { |
如果要將傳統函式改寫成箭頭函式 (Arrow Function),應該怎麼做呢?
答案是把 function
字眼拿掉並加上箭頭 =>
:
1 | var callSomeone = (someone) => { |
上面這個就是我們最常使用的箭頭函式的形式了!
當然,箭頭函式也能做一些縮寫。
某些情況下還能再 “縮寫”
當箭頭函式的內容只有 “一行” 的情況下,可以省略大括號 {}
,並把 return
拿掉。
單行情況下會自動 return
這樣就變成只有一行的形式:
1 | var callSomeone = (someone) => someone + '吃飯了'; |
而且參數 (someone)
的括號 ()
也可以省略:
1 | var callSomeone = (someone) => someone + '吃飯了'; |
但是,假如預設是 “不帶入” 參數的,那這個括號是不能省略的,至少要留一個括號:
1 | var callSomeone = () => '小明' + '吃飯了'; |
箭頭函式沒有 Arguments 參數
所謂 Arguments 參數,就是當我們帶入一堆數值,但是我們並沒有帶入函式的參數名稱時,可以用 arguments
這個變數來取代它們。
例如:
1 | const updateEasyCard = function () { |
但如果我們今天把這個函式改寫為箭頭函式,會出現 arguments is not defined
的報錯訊息。
原因是因為箭頭函式並沒有 Arguments 參數。
解法:在箭頭函式裡使用 “其餘參數”
如果想要在箭頭函式中,達成類似 Arguments 參數那樣 “大量使用參數” 的效果,可以使用之前學過的 “其餘運算符”。
使用 “其餘參數”:
1 | const updateEasyCard = (...arg) => { |
This 綁定的差異
this
的綁定是箭頭函式與傳統函式相差最大的地方,這裡也有許多陷阱。
傳統函式的 This
我們先看以下範例:
1 | var name = '全域阿婆'; |
我們明明是在 CallName
裡面執行 setTimeout
,為什麼第二個 this
卻是指向全域呢?
這是因為傳統函式的
this
是指向 **”函式的呼叫方式”**。
而這個 setTimeout
其實就等於 window.setTimeout
,
所以這裡的 this
是指向 window
,也就是全域。
箭頭函式的 This
我們把剛才的範例改寫成箭頭函式。
完成後,會發現所有的 this
都是指向全域。
1 | var name = '全域阿婆'; |
這是因為在物件內使用箭頭函式時,this
所指向的 “可能” 是全域。
為什麼是 “可能” 呢?
因為箭頭函式的 this
不一定是綁定在 window
上,可能是在其他物件上。
箭頭函式的
this
是綁定在它定義時所在的物件上。
觀念整理
在 Vue 的 methods 裡,建議用傳統函式
根據上面的案例,我們知道使用箭頭函式時,會比較不好掌握 this
的使用。
像是我們在寫 Vue 的 methods
時,很常使用 this
去取用元件的 data
,例如 this.name
這類的寫法。
這種時候如果我們使用的是 “箭頭函式”,那就滿可能會出錯的!
所以在 Vue 的 methods
裡面,會比較建議使用 “傳統函式” 配合 “縮寫” 的方式來呈現,例如:
1 | // 傳統函式 + 縮寫:callName(){...} |
這個寫法就跟傳統函式是一樣的結果。
那麼,到底什麼時候要用箭頭函式呢
這邊就說說該如何善用的箭頭函式。
下方範例中,內層的 console.log
是指向全域,
我們該如何將這個 this
改為指向 auntie
這個物件呢?
1 | var auntie = { |
這時候箭頭函式就能出場了。
一樣外層的 callName
是個傳統函式,但是內層的 setTimeout
我們把它改為箭頭函式。
接著宣告 var vm = this;
,這時候的 vm
就是指向 auntie
這個物件。
1 | var auntie = { |
有點像是我們之前取用 Vue 的 data
的做法。
補充:箭頭函式沒有自己的 This
「箭頭函式沒有自己的
this
」,要判斷this
基本上都是去找外層的this
。
最後再補充一下,上面只要 setTimeout
改成箭頭函式,this
就直接指向 auntie
了。
因為 setTimeout
為箭頭函式,所以要尋找它的 this
必須找它外層的 this
,
而它的外層 callName
如果是以 anuntie.callName
來呼叫,那便是指向 anuntie
,
所以 this.name
就等於 漂亮阿姨
。
以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫。