用函數式編程對JavaScript進行斷舍離

譯者按: 當從業20的JavaScript老司機學會函數式編程時,他扔掉了90%的特性,也不用面向對象了,最後發現了真愛啊!!!javascript

爲了保證可讀性,本文采用意譯而非直譯,而且對源代碼進行了大量修改。另外,本文版權歸原做者全部,翻譯僅用於學習。css

我和JavaScript

從1997年網景的Navigator 3瀏覽器開始就開始使用JavaScript。當時,JavaScript還只能作一些很簡單的事情。我記得最酷的就是用JavaScript實現mouseover特性,在那個時候已經算得上是高科技了!當鼠標移過去以後,文本內容就神奇的改變了。由於當時都是pre-DHTML,你根本不須要隱藏或則顯示DOM元素。html

關於DHTML(之前的 DHTML 現在是否是也算前端?):前端

DHTML是Dynamic HTML的簡稱,就是動態的html(標準通用標記語言下的一個應用),是相對傳統的靜態的html而言的一種製做網頁的概念。所謂動態HTML(Dynamic HTML,簡稱DHTML),其實並非一門新的語言,它只是HTML、CSS和客戶端腳本的一種集成,即一個頁面中包括html+css+javascript(或其它客戶端腳本),其中css和客戶端腳本是直接在頁面上寫而不是連接上相關文件。java

在那個時候,JavaScript的演化很慢,主要應用在表單驗證。所以,不像今天這麼火爆,並無引發太多的關注。能夠說只是一個錦上添花的附加物,你須要確保在瀏覽器禁用JavaScript以後,你的應用依然能夠正常使用。再日後,框架一個接着一個出現:jQuery,Knockout, Angular, React, Vue, 等等。redis

一樣,JavaScript也在加速演化。咱們才使用ES6不久,如今人們幾乎已經跳過ES7,開始討論ES8了。編程

而且,咱們有不少替代品,好比TypeScript,CoffeScript,ClojureScript, ELM,等等。瀏覽器

咱們已經被太多的框架和語言所淹沒,很難去跟蹤和掌握全部的語言和框架。閉包

錯誤路線

當JavaScript逐漸成熟,面向對象編程(OOP)的概念也滲入進來,並且我曾經很喜歡。框架

我開始嘗試全部不一樣的方法來建立類,我最終也能夠正確的使用繼承。我對本身說:JavaScript開始真的像一個語言了!

可是,直到多年之後我發現OOP是JavaScript引入的最糟糕的一個設計!

我嘗試將我對C#的理解帶入到JavaScript中去。一開始充滿期待,可是後來發現真的太複雜,太燒腦了。

這主要是由於JavaScript的原型繼承和C#不同,我已經習慣於天天編寫相似於console.log(this)這樣飄逸的代碼。可是如今呢?若是我一不當心沒按照規則來,那將會給我帶來噩夢。私有方法和私有值必需要在名字前面加上下劃線,甚至必須用閉包來保證私有性。

所以,不只OOP致使了不少問題,同時也因爲添加OOP帶來了不少新的問題。

函數式編程

一開始我並不理解。我能夠閱讀並理解這些用函數式編寫的代碼,可是不知道爲何!最終,我強迫我本身去學習它。我在在線教育網站EDX免費學習了函數式語言的入門課程,而後嘗試把這些技術運用到JavaScript中去。

函數式語言給了我一個全新的視角,讓我從一個徹底不一樣的方式去看待編程。

一開始會感到不天然,須要時間去適應。全部的定義都是基於函數,值不可更改,無狀態。我用函數式的思惟去解決問題。由於不熟悉,我花了更長的時間去學習。漸漸地,我熟練掌握了使用函數式的方法去編程。而且,我也知道全部代碼這樣編寫的內在含義。

個人代碼更加簡潔了,並且容易複用。漸漸的,我之前使用的那些語言特性從代碼中消失了,個人代碼看上去完像是用另外一個語言編寫。我還在用JavaScript嗎?

1. 再也不使用var

我用const替代了var。經過函數式的設計,個人函數都是純(pure)的。不會再去對一個變量進行值的變動操做,一樣也是爲了確保不會對其操做。

我會檢查代碼確保每個var,甚至let,全部聲明都使用const。

2. 沒有for循環

在學習程序語言的時候,咱們一開始就會學到for循環。可是自從學習了函數式編程,我將for循環都改爲了使用filter, map和reduce來實現。對於那些須要一些額外計算的需求,我會使用遞歸或則第三方庫好比lazy.js

在此,推薦個人另一篇專門介紹for循環博客:[Rethinking JavaScript: Death of the For Loop](Rethinking JavaScript: Death of the For Loop)

現在個人代碼裏面徹底沒有for循環了,若是你看到了,告訴我我會把它消除。

3. if也能夠被簡化

我開始中止在if裏面編寫大塊大塊的代碼。我將裏面的邏輯抽取出來單獨放在一個函數中。這樣,咱們就能夠將if用三元算子(a?b:c)來簡化。

在此,推薦個人另一篇專門介紹if博客:Rethinking JavaScript: The if statement

現在個人代碼裏面幾乎沒有if語句。爲了方便其餘開發者理解個人代碼,我不多使用它。

4. 和switch說拜拜

一樣,我也不喜歡用switch,而是尋找一個函數式的寫法。

推薦個人博客: Rethinking JavaScript: Eliminate the switch statement for better code

我也很喜歡用Ramda的cond算子來替代swtich。

5. 不在擔憂this

對的,你沒有聽錯!咱們也能夠徹底消除this。

函數式的JavaScript可讓你徹底拋棄使用煩人的this

如今只有數據和函數,甚至數據不過是函數的一種特殊表達形式,你不再須要this了。我開始將對象理解爲函數式語言中狀態(state)和函數。我甚至不須要把狀態或則函數和對象綁定到一塊兒,就像OOP中那樣。

我寫了一篇博客專門介紹如何解耦: Functional JavaScript: Decoupling methods from their objects

面向對象的設計不是必須的

如今往回看,我發現面型對象編程帶來的複雜度真的是沒必要要的。我可使用函數式語言實現一樣的功能,完成相同的任務。並且,代碼更加輕簡,由於不在須要將這些複雜的對象傳來傳去。只有數據和函數,並且由於函數沒有和對象綁定,更加容易複用。我不在須要擔憂傳統的原型繼承帶來的全部的問題,JavaScript設計的並很差。

JavaScript缺少私有、公有、內部或則被保護這類訪問控制器也再也不是一個問題。訪問控制器是用來解決因爲引入面向對象編程而設計的。在函數式的JavaScript中,這些問題不復存在。

總結

個人代碼如今看上去徹底不一樣。它包含了不少純函數,我將它們作成不一樣的ES6模塊。這些函數能夠被使用來構建更加複雜的函數。很大一部分函數都是很簡單的一行lambda表達式。

如今我看待軟件的思惟也變了:輸入是一個數據流,而後程序做用到該數據流上對數據進行各類操做,而後返回新的數據。

函數式設計對程序語言的影響以及無處不在,C#中的LINQ就是一個最佳的例子。一樣Java 8也引入了函數式語言的特性。

版權聲明:

轉載時請註明做者Fundebug以及本文地址:

https://blog.fundebug.com/2017/09/13/how-i-rediscovered-my-love-for-js/

相關文章
相關標籤/搜索