引言
JavaScript是一種強大的,卻被誤解的程式語言。一些人喜歡說它是一個物件導向的程式語言,或者它是一個函數語言程式設計語言。另外一些人喜歡說,它不是一個物件導向的程式語言,或者它不是一個函數語言程式設計語言。還有人認為它兼具面嚮物件語言和函式式語言的特點,或者,認為它既不是物件導向的也不是函式式的,好吧,讓我們先擱置那些爭論。
讓我們假設我們共有這樣的一個使命:在JavaScript語言所允許的範圍內,儘可能多的使用函數語言程式設計的原則來編寫程式。
本系列文章就是要讓你和我一起完成這樣的旅程。首先,我們需要清理下腦子裡那些關於函數語言程式設計的錯誤觀念。
在JS界被(重度)誤解的函數語言程式設計
顯然有相當一批開發者一天到晚的以函式式正規化的方式使用JavaScript。我還是要說有更大量的JavaScript開發者,並不真正理解那佯做的真正意義。
我確信,導致這種局面是因為很多用於服務端的web開發語言都源自C語言,而C語言,很顯然不是一種函數語言程式設計語言。
似乎有兩個層級的混亂,第一個層級的混亂我們用下面這個在jQuery中經常會用到的例子來說明:
1 2 3 4 |
$(".signup").click(function(event){ $("#signupModal").show(); event.preventDefault(); }); |
嘿,仔細看。我傳遞一個匿名函式作為引數,這在JavaScript世界裡被稱作眾所周知“CallBack”(回撥)函式。
真有人會認為這就是函數語言程式設計嗎?根本不是!
這個例子展示了一個函式式語言的關鍵特性:函式作為引數。另一方面,這個3行程式碼的例子也違背了幾乎所有其他的函數語言程式設計正規化。
第二個層級的混亂有點微妙。讀到這裡,一些追求潮流的JS開發者在暗自思考。
好吧,廢話!但是我已經知道了所有關於函數語言程式設計的知識與技能。我在我所有的專案上使用Underscore.js。
Underscore.js 是一個廣受歡迎的JavaScript庫,到處都在使用。舉個例子,我有一組單詞,我需要獲得一個集合,集合裡的每個元素是各個單詞的頭兩個字母。用Underscore.js實現這個相當簡單:
1 2 3 4 5 |
var firstTwoLetters = function(words){ return _.map(words,function(word){ return _.first(word,2); }); }; |
看!看JavaScript巫術。我正在使用這些高階的函式式應用函式,像_.map 和 _.first。你還有什麼要說的,利蘭(譯註:作者Leland)?
儘管underscore 和 像_.map這樣的函式是非常有價值的函式式正規化,但是像這個例子中所採用的組織程式碼的方法看起來…冗長而且對於我來說太難於理解。我們真的需要這樣做嗎?
如果開始思考的時候多一點“函式式”的思維,可能我們能夠把上面的例子改成這樣:
1 2 |
// ...一點魔法 var firstTwoLetters = map(first(2)); |
仔細想想,在1行程式碼中包含了和上面5行程式碼同樣的資訊。words 和word 僅僅是引數/佔位符。這個方法的核心是用一種更明顯的方式組合map函式,first函式,和常量2。
諸位可能會在這個例子中尋找,什麼會是其中的“一點魔法”。最終,把像上面提到的“一點魔法”放到任何一個例子中…某種小伎倆,不是嗎?好吧,我會在接下來的文章中闡釋“一點魔法”,所以呢,如果你有點好奇,請繼續關注!
這個系列的部落格文章目的是幫助人們瞭解如何在編寫JavaScript程式中借鑑那些函數語言程式設計語言的美好之處。
在下一篇文章中,我會討論JavaScript語言中那些函式式的元素和非函式式的元素。有了這些知識,我們會慢慢的拼湊出在JavaScript中一些函數語言程式設計的基礎構件。
更多內容預告:
- 第一部分:引言
- 第二部分:如何打造“函式式”程式語言
- 第三部分:.apply()、.call()以及arguments物件
- 第四部分:函式柯里化
- 第五部分:引數可變函式(敬請期待)
- 第六部分:一個真實的例子——2048 Game & Solver(敬請期待)
- 第七部分:惰性序列 / 集合(敬請期待)
- 第八部分:引數順序為何重要(敬請期待)
- 第九部分:Functors 和 Monads(敬請期待)