2024-11-04|閱讀時間 ‧ 約 0 分鐘

Day09 JavaScript 其他關鍵內容


今天要談的內容也是JavaScript很核心的部分,即使學完了先前的章節,馬上去看別人寫的JavaScript程式碼還是會看不懂,主要是因為JS開發者會採用各種簡化和替代的寫法,我們一一討論。

Anonymous(匿名) Function

首先我們要討論的是Anonymous(匿名) Function,在先前的章節中我們介紹過許多function的使用。那時候定義function一定會給名字,格式是這樣:

function 名稱() {}


但實際上在很多情況我們可以不給function指定名稱,我們稍微改寫一下的例子。

我們用document.addEventListener()來監聽'click'(滑鼠點擊),如果畫面被點擊eventAfterClicked()就會啟動,出現alert。

我們定義了eventAfterClicked()再把它放進addEventListener()的第二個參數,作為參考。但其實可以直接寫在參數裡面,這樣一來也不需要取名字,它就成為了anonymous function

我們直接在參數裡面寫這個function要幹嘛,而且沒有幫它取名字,這樣的function被稱為anonymous function。

它的格式就變成了:

function () {}

anonymous function常常出現在以function作為參數的情境(Higher-Order Function)。但值得注意的是,因為沒有名字,在其他地方完全無法取得這個function。所以如果那個function是需要重複使用的,最好還是另外定義。

Arrow(箭頭) Function

除了anonymous function,還有一種function的變體也很常出現,甚至幾乎是寫JS function的主流形式 — arrow function。

一樣用上面的例子,我們直接改寫成arrow function。

function這個關鍵字刪掉,並且加上=>在小括號後面,我們就完成改寫了。

這就是arrow function的格式:

() => {}

主要就是讓定義function這件事變得更簡單、更容易。


簡化Arrow Function

arrow function還可以進一步簡化。


同樣舉例來說。

我們有一個numbersarray,用map()這個method可以將它按照某種方式複製一份。map()的參數需要一個function,這個function會對每個numbers裡的元素做一次操作。每個元素是x,function回傳x * 2,於是最後我們可以得到一個數值被複製2倍的新array

順帶一提,原本的array不會被變更,因為map()不是mutating function。

這是我們之前就做過的事,目前只是把function改成anonymous的形式。


現在我們繼續改成arrow function,並一步一步簡化。

取消關鍵字function,加上=>就成了arrow function。


如果都寫在一行,return{}可以不寫(要一起不寫)。

arrow function沒有return和{}時會自動return後面的內容(x * 2)。


還可以再簡化!

arrow function的參數如果只有一個,可以不用寫()


這跟一開始差別可大了。

這也就是很多人看到arrow function不一定能理解的原因之一,它簡單的太過分了。但從省略關鍵字開始,我們一步一步了解了它如何變成現在這樣。


Arrow Function裡的this

arrow function裡還有一點很特別,我們先前提到的this關鍵字在這裡運作有點不同。讓我們回到上個單元的例子。

上個單元裡我們在eat()裡面再定義了一個function叫做hungry(),hungry()沒有特定對象呼叫它(不像me.eat()),所以this.firstName會呈現undefined。


我們可以把hungry()改寫成arrow function:

去掉function關鍵字,加上=>就變成arrow function。

要寫一個hungry()arrow function,我們會用let=再接arrow function。

這裡的this沒有因為在hungry()內需要另外處理。

從這裡可以看見,arrow function不會像傳統function一樣讓this的值被覆寫掉(寫在hungry()裡面和外面的this值都一樣!),是比較簡單、比較直覺的。


arrow function除了比較簡潔以外,還有保留context的特色,讓它成為大多工程師的第一個選擇。

Function Hoisting(提升)

我們之前就已經看過幾次這種情境了。

先使用function再定義function在JavaScript裡面是可行的。


這樣其實不太合理,因為程式碼是一行一行執行的,通常都要先定義才能使用。

可以這樣寫的原因就是function hoisting的機制,用function關鍵字定義的會在背後被JS hoisting到最上方,優先處理。換句話說,在我們看不到的層面,其實定義sayHello()那幾行會被放在實際執行它之前,這段才會正常運作。


但除此之外,我們也見到了其他定義function的方式。

這是兩種把anonymous function指定成變數的方式。

但這兩種寫法都沒有function hoisting,所以會出錯。神奇吧…這就是JavaScript的運作方式。

其實總歸一句,就不要再定義之前先用function嘛,這樣還滿不符合邏輯的,不太建議。不過至少你現在知道為什麼那些情況在JS裡面也是可行了。

Template Literal(模板字串)

之前把字串連接起來我們都是用””’’+這類的符號,寫起來又臭又長。

除了這種寫法以外,還有一種叫做template literal的方式。主要是用backtick(``)來取代''"",backtick位在鍵盤上esc的下方或者在某些鍵盤中是esc本身透過組合鍵產生。


用template literal來改寫上述例子:

我們可以把``想成是有特殊功能的""'',基本上引號能做到的它也能做到,但是多了一種能在文字中插入變數的能力。使用${}配合,就可以在string中放入變數或者計算式。用另外的角度說,在${}內可以寫JavaScript。上面的例子中我們就將me這個變數用template literal放入一串string之中。


如果裡面要放其他的JavaScript也都可以。

${}內的2+2被計算成4了。

比起原本的方式更加簡潔好寫了,是很推薦的用法。

關於分號

如同之前提到的,在JavaScript裡面有沒有加;在結尾都是可行的,在某些程式語言裡並不是這樣。這個運作邏輯是,「如果正常的換行,JavaScript在執行的時候會自動加上分號。」,我們看以下的例子。

JavaScript會自動的在我們看不見的地方補上分號,給它正確的換行作為判斷標準是很重要的。我們其實也不太會把一堆東西寫在同一行啦,只是讓大家了解背後的機制。如果你換行換得太奇怪,大多編譯器的formatter都會幫你處理,也會跟你說哪裡有錯,不太需要擔心。至於要不要加分號,在JavaScript裡就變成了一種選項,有些人習慣、有些人不愛,大家也不要太糾結在這件小事上,讓formatter來為你處理就好。

=====

我們在條件判斷的單元裡看過==,但在實際上我們可能更常看到用===作為條件判斷。從先前的單元裡面我們看見其實JS好像不那麼要求變數的type(類別),這是因為JS內建一個自動的轉換機制,自動判斷類別。

舉例來說:

==會允許自動型別轉換,string’3’和number3會因為這樣變得一樣,===則不允許。所以在使用===的情況下,兩者要typevalue都一樣,才會回傳true。這樣是比較嚴謹的。


目前看起來問題還不算太大,但還有很多例子這樣的操作顯得不太合理。

就以第一個為例,假設我是想要判斷使用者是不是沒輸入資料(情況應該是’’空字串),但使用者輸入0也被算進來,就很奇怪。下面兩個例子更是尤其,而且除此之外還有更多非常離奇、難判斷的例子。因此普遍的建議是嚴謹一點,使用===來作判斷。

小結

今天我們談了非常多在JavaScript裡面常見的寫法以及某些特殊的規則,再加上前面幾單元的內容,希望比之前更了解JS程式碼的運作方式。例如,常見array後出現一長串連續map()filter()再加上anonymous arrow function,第一次看見還真的會被嚇到,今天開始你可以知道這是怎麼回事了。


明天,我們會討論JavaScript語法中備受關注的的內容,async和await語法。如同之前我們看到function hoisting的應用,JS程式碼不總是照著順序逐個運作的,有些情況下我們希望它不要這樣做。在最後這個單元中,我們將面對這個稍具挑戰的主題。


Resource

今日Codepen

連結

Credits

關於我

我是Erkin, 一個網站開發者。
有任何疑問或是想勘誤的話歡迎聯繫。

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.