如果理解直接看為一等公民的好處好處。
其實說函數式一等公民的意思就是說函數和其他“公民”具有相同的屬性。就像任何一種數據類型,它能夠被存儲在數組中,能夠作為函數的參數,能夠賦值給變量:
上面的代碼沒有什么意義,只是表達函數在JavaScript中是一等公民,和一個值一樣。
拿一個callback的例子來講,比如你用fetch發個請求時:
上面其實可以直接傳遞一個函數作為回調,加一層包裹其實沒有必要:
多一層函數的包裹并沒有任何意義,完全是多余的代碼。再看一個例子:
上面的代碼其實就是聚合一些功能作為一個對象,但是多加了一層的函數,也是沒有必要的,在閱讀的時候到會增加復雜度,其實postController.find === Db.find,所以完全沒有再去包裹一層函數:
上面的代碼是不是更表意,然而如果js的函數不能像值一樣傳遞,上面的簡寫都是不可能的。上面的代碼其實還有一個好處,你不用去糾結如何命名在兩層函數之間的參數了。這種風格代碼是符合Pointfree的,我們后面要介紹。另外,函數式編程是操作函數的,所以函數是一等公民也是函數式的基石,基本上如果js不支持這一項,函數式根本玩不轉。
讓我舉一個例子,大家在小學多學過一元一次方程吧:
這就是一個純函數,一個輸入然后返回一個輸出。所有的東西都是圍繞輸入的,一個輸入只可能返回一個輸出,然后對任何其他沒在作用域中的變量沒有任何操作。
更書面的解釋:一個純函數一個輸入永遠都只有一個同樣的輸出,然后不會產生任何副作用。副作用是啥我們一會兒再說。
通常不純的函數分為兩類,一種是會改變輸入的:
上面中在numbers這個數組上面的兩個方法,slice是純函數。而splice則不是純函數,它會改變輸入的數值。做了額外的事。
另外一種是對函數以外的狀態有依賴的:
像上面的函數,第一個就是不純的,他依賴的作用域之外的一個變量,一旦這個變量改變,這個函數返回的值就會跟著改變。
副作用就是在函數計算過程中,對函數外的狀態進行更改或則與函數外狀態進行交互的行為。首先副作用會導致函數不純,是程序有不可控的依賴,不便于管理。但是,副作用是不可消除的,在正常的編程活動中是必然伴隨著副作用的。所以在面對副作用時,問題不是如何消除副作用,而是如何管理副作用。這個,會在我們講解范疇論相關概念的時候再深入。
正常編程活動中會引入的副作用有這些:
當然不限于上面這幾種,還有很多行為都帶有副作用。
純函數的每次輸入和輸出都是沒有狀態的,所以結果都一樣,能夠被緩存在任何地方而不會造成錯誤。
第二個signUp依賴是從上傳遞的,所以能直觀的看出saveUser需要Db,welcomeUser還需要Email。在不純的函數中你很難在調用的時候知道他的依賴,你需要查看代碼,才能搞清楚,“哦,原來還用了Db存了波數據啊?!?
依賴作為參數傳入,也很容易的在移植到其他場景使用,畢竟函數只是功能,針對不同場景操作不同的數據。
寫單測的時候,最麻煩的就是如何mock數據。通常有兩類數據最難mock,第一個是全局變量,比如document,另外一類是import進來的依賴,對于這兩種,雖然在一些測試套件中有現成的工具庫去mock。但是,都是很詭異的方式。
而如果是函數式的話,你測的就是一個輸入一個輸出,沒有外部的影響,是非常容易測試的。
純函數都是沒有狀態的,那即使跑在多臺機器多個進程,每個單元相互之間是沒有耦合關系的。
大家可以看阮老師的這篇博客了解一下:http://www.ruanyifeng.com/blo...
我只扯一下Pointfree風格代碼的好處:
當然也有人認為其將太多的狀態隱藏了,初讀代碼很難理解,只有看了具體函數實現功能才能知道真正的意圖,對于代碼的可讀性而言,很糟糕。
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。