在開始討論這兩個陌生的名詞之前,我們先準備一份資料以便後續測試使用。
這筆資料是users
的資料,可能是社群平台用來記錄使用者資料的格式。其中users
是一個array(有[]
包著),裡面包含了3個Object(有{}
包著),每個Object內有許多的property-value配對(如id: 3
、username: “kbrunton2”
等),以逗號分隔,換行只是因為方便閱讀。
接著使用之前講過,每個array內建的push()
method,將一筆新的資料放進users
的最後。然後用console.log()
來看看users
裡面現在是什麼。
我們會發現users
現在有編號0-3(紫色的數字),是總共4筆使用者資料的array了。
這不是什麼新內容,我們之前就學過array裡包含著object的情況,也見過array的push()
method。現在再次提到,是因為這就是了解Mutating Function和Returning Function的絕佳範例。
Mutating的意思「改變」,Mutating Function的意思是這個function會改變原本的值。以push()
為例,本來只有3個內容的的arrayusers
被push()
這個method改變成4個內容。特別的事,push()
做的不只是這樣,它還會Return(回傳)一個數值,被改變過後的array的長度(在這個情況就是4
)。
我們可以把整串給印出來,看看這是如何運作的。
users.push()
會回傳新array的長度(4
),這個數值被console.log()
印在Console裡面,我們就會看見4
。像這樣會回傳一個值的function被稱作Returning Function。
你會發現push()
method同時擁有兩種身份,它是Mutating Function,也是Returning Function。這件事情為什麼那麼重要?因為JavaScript內建常用的method行為各有差異,有些只是Mutating Function,有些是Returning,有些就像這個例子,兩者都是。光是事先了解一個method是哪種類別,你就可以預測它的行為。
有些人會覺得JS這樣的設計是靈活的,有些人覺得是凌亂的,褒貶不一。
map()
是其中一個array內建的method,它幾乎就是最常見的那個。map()
常常用在將array資料根據某種條件複製一份。舉例來說,假設我只需要上述users
的資料中name
的那一項,而且也想將這些使用者的name
存成array的形式,就很適合使用map()
。
我們可以這樣寫:
map()
會根據條件回傳一個新的array,它不會Mutate(變更)原本的users
array。換句話說map()
是一個Returning Function而不是Mutating Function。而map()
會需要一個function作為參數,讓它知道根據什麼條件回傳,因此它也是一個Higher-Order Function。我們繼續看下去。
map()
裡面需要一個function作為參數,我們定義一個onlyNameTest()
來供它使用。map()
會做的事就是對每一個users
array裡的元素做一次onlyNameTest()
這個操作,然後把onlyNameTest()
回傳的內容放進新的array裡面。
以目前的情況為例,這個onlyNameTest()
會執行4次(因為users
array有4個元素),每一次都會回傳”hello”
,放進新的array裡面。
結果就是newArray
裡面會有4個”hello”
。
現在我們來嘗試製作一個只有username
的新array。
我們一樣使用map()
來根據舊的array產生新的。其中users
裡的每個項目都會被onlyName()
function作為參數使用,我們把參數命名成user
。接下來只要回傳每一個user
的username
這個property就可以了,用.
來存取username
。
最後把這個結果儲存到新的arrayusersOnlyName
,並印在Console。
成功得到一個新的長度為4的array,裡面只有username
,而且原本的users
array並沒有被改變。
filter()
在各方面都跟map()
很類似,它一樣是array的method、會回傳一個新的array、需要另一個function作為參數等等。
假設我們現在想要找出所有gender: “Female”
的資料,並且同樣存在array裡面,filter()
完美的完成這個任務。
同樣的,在filter()
參數這裡我們傳給它一個functiononlyFemale()
,讓它重複執行,在這情況下它一樣會執行4次(因為array的長度是4)。跟map()
不同的是,filter()
的機制是根據onlyFemale()
回傳的結果是true
或是false
來決定要不要把內容放進新array。
用這個user.gender == ‘Female’
條件判斷是不是該保留。最後就可以得到gender: ‘Female’
的新array了。
可以發現array的長度剩3,因為在users
裡面只有3個gender: ‘Female’
的資料,它們被filter()
成功的過濾出來了。
到這裡可能還是讓人困惑,到底為什麼要特別介紹幾個method?主要是這對我們了解HOF在JS的運作很有幫助,因為第一眼見到以下的內容會顯得很奇怪。
我們再接著定義另一個function用來filter,這個function叫做onlyIdLargerThanTwo()
用來找到id
> 2的user。
從這段可以看見一個JavaScript特殊的使用方式,我連續使用了兩個filter()
。由於第一個filter()
是Returning Function會回傳一個新array,新的array又可以用filter()
method,可以一直按照這種方式接續下去,變成一個chain(鏈)。
由於map()
也是Returning Function,我們也可以在後面加上map()
,並使用一開始定義的onlyName()
function只留下名稱。
最後呈現出來的結果就是符合gender: 'Female'
又符合id > 2
的使用者的username
。
這種連續使用的情境在JS裡面屢見不鮮,由於這些內建的method都是會回傳array的Returning Function,才得以實現這種寫法,這也是我們特別介紹特定這幾個method的原因。第一次見的人可能會無法理解為什麼寫了一長串。
在今天的內容裡,我們了解什麼是Mutating Function和Returning Function。其中很特別的是Returning Function在某些特定的情況下可以連續的使用、串接在一起,這是JavaScript裡面很常見的操作,而且不僅限於在array上運用。這讓map()
和filter()
之類的method,即使不變更原來array的值(not mutating),依然強大好用。
明天,我們會討論Context & Scope,這是連資深工程師都可能需要花點時間釐清的部分,我們會一一討論。
我是Erkin, 一個網站開發者。
有任何疑問或是想勘誤的話歡迎聯繫。