溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離

發(fā)布時(shí)間:2020-06-29 18:40:40 來(lái)源:網(wǎng)絡(luò) 閱讀:119 作者:Fundebug 欄目:web開(kāi)發(fā)

譯者按: 當(dāng)從業(yè)20的JavaScript老司機(jī)學(xué)會(huì)函數(shù)式編程時(shí),他扔掉了90%的特性,也不用面向?qū)ο罅?,最后發(fā)現(xiàn)了真愛(ài)?。。。?/p>

  • 原文: How I rediscovered my love for JavaScript after throwing 90% of it in the trash.
  • 譯者: Fundebug

為了保證可讀性,本文采用意譯而非直譯,并且對(duì)源代碼進(jìn)行了大量修改。另外,本文版權(quán)歸原作者所有,翻譯僅用于學(xué)習(xí)。

我和JavaScript

從1997年網(wǎng)景的Navigator 3瀏覽器開(kāi)始就開(kāi)始使用JavaScript。當(dāng)時(shí),JavaScript還只能做一些很簡(jiǎn)單的事情。我記得最酷的就是用JavaScript實(shí)現(xiàn)mouseover特性,在那個(gè)時(shí)候已經(jīng)算得上是高科技了!當(dāng)鼠標(biāo)移過(guò)去之后,文本內(nèi)容就神奇的改變了。因?yàn)楫?dāng)時(shí)都是pre-DHTML,你根本不需要隱藏或則顯示DOM元素。

關(guān)于DHTML(以前的 DHTML 如今是不是也算前端?):

DHTML是Dynamic HTML的簡(jiǎn)稱,就是動(dòng)態(tài)的html(標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言下的一個(gè)應(yīng)用),是相對(duì)傳統(tǒng)的靜態(tài)的html而言的一種制作網(wǎng)頁(yè)的概念。所謂動(dòng)態(tài)HTML(Dynamic HTML,簡(jiǎn)稱DHTML),其實(shí)并不是一門新的語(yǔ)言,它只是HTML、CSS和客戶端腳本的一種集成,即一個(gè)頁(yè)面中包括html+css+javascript(或其它客戶端腳本),其中css和客戶端腳本是直接在頁(yè)面上寫而不是鏈接上相關(guān)文件。

在那個(gè)時(shí)候,JavaScript的演化很慢,主要應(yīng)用在表單驗(yàn)證。因此,不像今天這么火爆,并沒(méi)有引起太多的關(guān)注??梢哉f(shuō)只是一個(gè)錦上添花的附加物,你需要確保在瀏覽器禁用JavaScript之后,你的應(yīng)用依然可以正常使用。再往后,框架一個(gè)接著一個(gè)出現(xiàn):jQuery,Knockout, Angular, React, Vue, 等等。

同樣,JavaScript也在加速演化。我們才使用ES6不久,現(xiàn)在人們幾乎已經(jīng)跳過(guò)ES7,開(kāi)始討論ES8了。

并且,我們有很多替代品,比如TypeScript,CoffeScript,ClojureScript, ELM,等等。

我們已經(jīng)被太多的框架和語(yǔ)言所淹沒(méi),很難去跟蹤和掌握所有的語(yǔ)言和框架。

錯(cuò)誤路線

當(dāng)JavaScript逐漸成熟,面向?qū)ο缶幊?OOP)的概念也滲入進(jìn)來(lái),而且我曾經(jīng)很喜歡。

我開(kāi)始嘗試所有不同的方法來(lái)創(chuàng)建類,我最終也可以正確的使用繼承。我對(duì)自己說(shuō):JavaScript開(kāi)始真的像一個(gè)語(yǔ)言了!

但是,直到多年以后我發(fā)現(xiàn)OOP是JavaScript引入的最糟糕的一個(gè)設(shè)計(jì)!

我嘗試將我對(duì)C#的理解帶入到JavaScript中去。一開(kāi)始充滿期待,但是后來(lái)發(fā)現(xiàn)真的太復(fù)雜,太燒腦了。

這主要是因?yàn)镴avaScript的原型繼承和C#不一樣,我已經(jīng)習(xí)慣于每天編寫類似于console.log(this)這樣飄逸的代碼。但是現(xiàn)在呢?如果我一不小心沒(méi)按照規(guī)則來(lái),那將會(huì)給我?guī)?lái)噩夢(mèng)。私有方法和私有值必須要在名字前面加上下劃線,甚至必須用閉包來(lái)保證私有性。

因此,不僅OOP導(dǎo)致了很多問(wèn)題,同時(shí)也由于添加OOP帶來(lái)了很多新的問(wèn)題。

函數(shù)式編程

一開(kāi)始我并不理解。我可以閱讀并理解這些用函數(shù)式編寫的代碼,但是不知道為什么!最終,我強(qiáng)迫我自己去學(xué)習(xí)它。我在在線教育網(wǎng)站EDX免費(fèi)學(xué)習(xí)了函數(shù)式語(yǔ)言的入門課程,然后嘗試把這些技術(shù)運(yùn)用到JavaScript中去。

函數(shù)式語(yǔ)言給了我一個(gè)全新的視角,讓我從一個(gè)完全不同的方式去看待編程。

一開(kāi)始會(huì)感到不自然,需要時(shí)間去適應(yīng)。所有的定義都是基于函數(shù),值不可更改,無(wú)狀態(tài)。我用函數(shù)式的思維去解決問(wèn)題。因?yàn)椴皇煜?,我花了更長(zhǎng)的時(shí)間去學(xué)習(xí)。漸漸地,我熟練掌握了使用函數(shù)式的方法去編程。并且,我也知道所有代碼這樣編寫的內(nèi)在含義。

我的代碼更加簡(jiǎn)潔了,而且容易復(fù)用。漸漸的,我以前使用的那些語(yǔ)言特性從代碼中消失了,我的代碼看上去完像是用另一個(gè)語(yǔ)言編寫。我還在用JavaScript嗎?

1. 不再使用var

我用const替代了var。通過(guò)函數(shù)式的設(shè)計(jì),我的函數(shù)都是純(pure)的。不會(huì)再去對(duì)一個(gè)變量進(jìn)行值的變更操作,同樣也是為了確保不會(huì)對(duì)其操作。

我會(huì)檢查代碼確保每一個(gè)var,甚至let,所有聲明都使用const

2. 沒(méi)有for循環(huán)

在學(xué)習(xí)程序語(yǔ)言的時(shí)候,我們一開(kāi)始就會(huì)學(xué)到for循環(huán)。但是自從學(xué)習(xí)了函數(shù)式編程,我將for循環(huán)都改成了使用filter, map和reduce來(lái)實(shí)現(xiàn)。對(duì)于那些需要一些額外計(jì)算的需求,我會(huì)使用遞歸或則第三方庫(kù)比如lazy.js。

在此,推薦我的另外一篇專門介紹for循環(huán)博客:[Rethinking JavaScript: Death of the For Loop](Rethinking JavaScript: Death of the For Loop)

如今我的代碼里面完全沒(méi)有for循環(huán)了,如果你看到了,告訴我我會(huì)把它消除。

3. if也可以被簡(jiǎn)化

我開(kāi)始停止在if里面編寫大塊大塊的代碼。我將里面的邏輯抽取出來(lái)單獨(dú)放在一個(gè)函數(shù)中。這樣,我們就可以將if用三元算子(a?b:c)來(lái)簡(jiǎn)化。

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

如今我的代碼里面幾乎沒(méi)有if語(yǔ)句。為了方便其他開(kāi)發(fā)者理解我的代碼,我很少使用它。

4. 和switch說(shuō)拜拜

同樣,我也不喜歡用switch,而是尋找一個(gè)函數(shù)式的寫法。

推薦我的博客: Rethinking JavaScript: Eliminate the switch statement for better code

我也很喜歡用Ramda的cond算子來(lái)替代swtich。

5. 不在擔(dān)心this

對(duì)的,你沒(méi)有聽(tīng)錯(cuò)!我們也可以完全消除this。

函數(shù)式的JavaScript可以讓你完全拋棄使用煩人的this

現(xiàn)在只有數(shù)據(jù)和函數(shù),甚至數(shù)據(jù)不過(guò)是函數(shù)的一種特殊表達(dá)形式,你再也不需要this了。我開(kāi)始將對(duì)象理解為函數(shù)式語(yǔ)言中狀態(tài)(state)和函數(shù)。我甚至不需要把狀態(tài)或則函數(shù)和對(duì)象綁定到一起,就像OOP中那樣。

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

面向?qū)ο蟮脑O(shè)計(jì)不是必須的

現(xiàn)在往回看,我發(fā)現(xiàn)面型對(duì)象編程帶來(lái)的復(fù)雜度真的是不必要的。我可以使用函數(shù)式語(yǔ)言實(shí)現(xiàn)同樣的功能,完成相同的任務(wù)。而且,代碼更加輕簡(jiǎn),因?yàn)椴辉谛枰獙⑦@些復(fù)雜的對(duì)象傳來(lái)傳去。只有數(shù)據(jù)和函數(shù),而且因?yàn)楹瘮?shù)沒(méi)有和對(duì)象綁定,更加容易復(fù)用。我不在需要擔(dān)心傳統(tǒng)的原型繼承帶來(lái)的所有的問(wèn)題,JavaScript設(shè)計(jì)的并不好。

JavaScript缺乏私有、公有、內(nèi)部或則被保護(hù)這類訪問(wèn)控制器也不再是一個(gè)問(wèn)題。訪問(wèn)控制器是用來(lái)解決由于引入面向?qū)ο缶幊潭O(shè)計(jì)的。在函數(shù)式的JavaScript中,這些問(wèn)題不復(fù)存在。

總結(jié)

我的代碼現(xiàn)在看上去完全不同。它包含了很多純函數(shù),我將它們做成不同的ES6模塊。這些函數(shù)可以被使用來(lái)構(gòu)建更加復(fù)雜的函數(shù)。很大一部分函數(shù)都是很簡(jiǎn)單的一行l(wèi)ambda表達(dá)式。

現(xiàn)在我看待軟件的思維也變了:輸入是一個(gè)數(shù)據(jù)流,然后程序作用到該數(shù)據(jù)流上對(duì)數(shù)據(jù)進(jìn)行各種操作,然后返回新的數(shù)據(jù)。

函數(shù)式設(shè)計(jì)對(duì)程序語(yǔ)言的影響以及無(wú)處不在,C#中的LINQ就是一個(gè)最佳的例子。同樣Java 8也引入了函數(shù)式語(yǔ)言的特性。

關(guān)于Fundebug

Fundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java實(shí)時(shí)BUG監(jiān)控。 自從2016年雙十一正式上線,F(xiàn)undebug累計(jì)處理了7億+錯(cuò)誤事件,得到了Google、360、金山軟件、百姓網(wǎng)等眾多知名用戶的認(rèn)可。歡迎免費(fèi)試用!

用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離

版權(quán)聲明

轉(zhuǎn)載時(shí)請(qǐng)注明作者Fundebug以及本文地址:

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

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI