摘要:函數(shù)式編程是一種以函數(shù)為基礎(chǔ)的編程方式和代碼組織方式,從程序員的思路上來說,就是將程序拆分并抽象成多個函數(shù),再組裝回去。在這門語言中,函數(shù)是一等公民,函數(shù)可以作為函數(shù)的參數(shù),函數(shù)也可以返回一個函數(shù),因此適合函數(shù)式編程風(fēng)格。
函數(shù)式編程 ( Functional Programming ) 是一種以函數(shù)為基礎(chǔ)的編程方式和代碼組織方式,從程序員的思路上來說,就是將程序拆分并抽象成多個函數(shù),再組裝回去。
在JavaScript這門語言中,函數(shù)是一等公民,函數(shù)可以作為函數(shù)的參數(shù),函數(shù)也可以返回一個函數(shù),因此適合函數(shù)式編程風(fēng)格。
函數(shù)式風(fēng)格的編程,長于數(shù)據(jù)的處理,且所謂“處理”并不改變數(shù)據(jù)本身。JavaScript中,數(shù)據(jù)總是以對象的形式出現(xiàn),也就是說,函數(shù)式的編程對于“接收對象A→處理→處理→處理→得出新對象B”這樣的流程可以很優(yōu)雅地實(shí)現(xiàn),且不影響對象A本身。
對于JavaScript程序員(無論是前端還是后端),最常見且實(shí)用的編程模式當(dāng)然是抽象出類(以構(gòu)造函數(shù)的形式)并實(shí)例化,然后在實(shí)例上調(diào)用方法。函數(shù)式風(fēng)格的編程不是為了取代這種編程模式,而是為了與之形成互補(bǔ)。
一些特點(diǎn):
不改變輸入的數(shù)據(jù)
不耦合,也就是說,函數(shù)盡量不影響甚至知曉外部的狀態(tài)
保持?jǐn)?shù)據(jù)組織形式的簡單,例如,盡量使用JavaScript原生的數(shù)據(jù)結(jié)構(gòu)(對象、數(shù)組等)
函數(shù)在函數(shù)式編程中,任何代碼可以都是函數(shù),且要求具有返回值,如下示例
// 非函數(shù)式 var title = "Functional Programming"; var saying = "This is not"; console.log(saying + title); // => This is not Functional Programming // 函數(shù)式 var say = title => "This is " + title; var text = say("Functional Programming"); // => This is Functional Programming純函數(shù)
純函數(shù)在這里指函數(shù)內(nèi)外間是“無”關(guān)聯(lián)的。主要有下面兩點(diǎn)
沒有副作用(side effect)
不會涉及到外部變量的使用或修改
引用透明
函數(shù)內(nèi)只會依賴傳入?yún)?shù),在任何時(shí)候?qū)瘮?shù)輸入相同的參數(shù)時(shí),總能輸出相同的結(jié)果
// 非純函數(shù)(函數(shù)內(nèi)依賴函數(shù)外的變量值) var title = "Functional Programming"; var say = ()=> "This is not" + title; // <= 依賴了全局變量 title // 純函數(shù) var say = (title)=>"This is " + title; // <= 依賴了以參數(shù) title 傳入 say("Functional Programming");不可變數(shù)據(jù)(immutable)
這里主要是指變量值的不可變。當(dāng)需要基于原變量值改變時(shí),可通過產(chǎn)生新的變量來確保原變量的不變性,如下
// 可變數(shù)據(jù) var arr = ["Functional", "Programming"]; arr[0] = "Other"; // <= 修改了arr[0]的值 console.log(arr) // => ["Other", "Programming"] // 變量arr值已經(jīng)被修改 // 不可變數(shù)據(jù) var arr = ["Functional", "Programming"]; // 得到新的變量,不修改了原來的值 var newArr = arr.map(item => { if(item === "Functional"){ return "Other"; } else { return item; } }) console.log(arr); // => ["Functional", "Programming"] 變量arr值不變 console.log(newArr); // => ["Other", "Programming"] 產(chǎn)生新的變量newArr
之所以使用這種不變值,除了更好的函數(shù)式編程外,還能夠維持線程安全可靠,實(shí)際上也能讓代碼更加清晰。
設(shè)想,如果你定義了一個變量A,A在其他地方被其他人修改了,這樣是不方便定位A的當(dāng)前值的。
使用 map, reduce 等數(shù)據(jù)處理函數(shù)
強(qiáng)大的 JavaScript 有著越來越多的高能處理數(shù)據(jù)函數(shù),其中包含了 map、 reduce、 filter 等。
map 能夠?qū)υ瓟?shù)組中的值進(jìn)行逐個處理并產(chǎn)生新的數(shù)組,一個簡單例子
// map var data = [1, 2, 3]; var squares = data.map( (item, index, array) => item * item ); console.log(squares); // => [1, 4, 9] console.log(data);// => [1, 2, 3] data 還是那個 data
reduce 能夠?qū)υ瓟?shù)組中的各個值進(jìn)行結(jié)合處理,來產(chǎn)生新的值,如下面例子中,previous 代表上一個值,current 代表當(dāng)前值,reduce 函數(shù)可以傳入第二個參數(shù)作為 previous 初始值,不傳時(shí)則 previous 初始值為數(shù)組中第一個值。
// reduce var sum = [1, 2, 3].reduce( (previous, current, index, array) => previous + current ); console.log(sum); // => 6函數(shù)柯里化 Currying
柯里化 是將多參函數(shù)轉(zhuǎn)換成一系列的單參函數(shù)。結(jié)合下面例子來說明下
// 一個多參函數(shù) var add = (a, b) => a + b; add(1, 2); // => 3
將上面的多參函數(shù)進(jìn)行柯里化,如下
// 柯里化函數(shù) var add = a => b => a + b;
上面柯里化后的函數(shù)調(diào)用方式也有所轉(zhuǎn)變,第一次傳入一個參數(shù)返回了一個函數(shù),再傳入?yún)?shù)則完成整體的調(diào)用,這也是利用的閉包的特性
var add1 = add(1); add1(2); // => 3
柯里化后的函數(shù),也可以應(yīng)用在生產(chǎn) “ 函數(shù) ” 上,如下示例
var say = title => type => title + " is " + type; var sayFP = say("Functional Programming"); var sayOther = say("Other Programming"); sayFP("good"); // => Functional Programming is good sayOther("good"); // => Other Programming is good組合函數(shù) compose
顧名思義,組合函數(shù)是將多個函數(shù)進(jìn)行組合成一個函數(shù)。舉個例子
var compose = (fn1, fn2) => (arg) => fn1(fn2(arg)); var a = arg => arg + "a"; var b = arg => arg + "b"; var c = compose(a, b); // 將a,b函數(shù)進(jìn)行組合 c("c"); // => cba
上面示例中,當(dāng)調(diào)用組合函數(shù) c 時(shí),傳入的參數(shù)會經(jīng)過 b 函數(shù),接著將 b 函數(shù)的返回值作為 a 函數(shù)的參數(shù)值,從而輸出最終結(jié)果。
組合函數(shù) c 就像管道一樣,將水流( 返回值 )流經(jīng)各個函數(shù)中進(jìn)行處理。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/87930.html
摘要:前言繼續(xù)向下看廖大教程,看到了函數(shù)式編程這一節(jié),當(dāng)時(shí)是覺得沒啥用直接跳過了,這次準(zhǔn)備要仔細(xì)看一遍了,并記錄下一些心得。 前言 繼續(xù)向下看廖大教程,看到了函數(shù)式編程這一節(jié),當(dāng)時(shí)是覺得沒啥用直接跳過了,這次準(zhǔn)備要仔細(xì)看一遍了,并記錄下一些心得。 函數(shù)式編程 上學(xué)期有上一門叫 人工智能 的課,老師強(qiáng)行要我們學(xué)了一個叫做 prolog 的語言,哇那感覺確實(shí)難受,思維方式完全和之前學(xué)過的不一樣,...
摘要:以我自己的理解,函數(shù)式編程就是以函數(shù)為中心,將大段過程拆成一個個函數(shù),組合嵌套使用。越來越多的跡象表明,函數(shù)式編程已經(jīng)不再是學(xué)術(shù)界的最愛,開始大踏步地在業(yè)界投入實(shí)用。也許繼面向?qū)ο缶幊讨?,函?shù)式編程會成為下一個編程的主流范式。 使用React也滿一年了,從剛剛會使用到逐漸探究其底層實(shí)現(xiàn),以便學(xué)習(xí)幾招奇技淫巧從而在自己的代碼中使用,寫出高效的代碼。下面整理一些知識點(diǎn),算是React看書...
摘要:數(shù)據(jù)和視圖的分離更符合面向?qū)ο蟮木幊?,的?shí)現(xiàn)也是和一樣用虛擬來實(shí)現(xiàn)的,至于什么是虛擬,就是用通過模板渲染而成的。 Vue是當(dāng)今熱門的框架,他可以進(jìn)行數(shù)據(jù)雙向綁定,為什么vue會大受歡迎,我知道的原因大致如下?1.傳統(tǒng)改變dom結(jié)構(gòu)的操作是非常浪費(fèi)性能的操作(就是慢)2.把dom結(jié)構(gòu)改變的邏輯放在js層來做可以提高性能。3.數(shù)據(jù)和視圖的分離更符合面向?qū)ο蟮木幊蹋琺vvm vue的實(shí)現(xiàn)也是...
摘要:是一門最近比較流行的靜態(tài)類型編程語言,而且和一樣同屬系。這個生成的構(gòu)造函數(shù)是合成的,因此不能從或中直接調(diào)用,但可以使用反射調(diào)用。 showImg(https://segmentfault.com/img/remote/1460000012958496); Kotlin是一門最近比較流行的靜態(tài)類型編程語言,而且和Groovy、Scala一樣同屬Java系。Kotlin具有的很多靜態(tài)語言...
摘要:在學(xué)習(xí)的過程中時(shí)常會聽到一個名次函數(shù)式編程,那么究竟什么是函數(shù)式編程,函數(shù)式編程又有什么優(yōu)點(diǎn),這就在這篇博客進(jìn)行一個簡單的總結(jié)吧主要內(nèi)容函數(shù)式編程的概念函數(shù)式編程的優(yōu)點(diǎn)與示例什么是函數(shù)式編程首先,我們放下編程的概念,我們來看函數(shù)。 在學(xué)習(xí) JS 的過程中時(shí)常會聽到一個名次——函數(shù)式編程,那么究竟什么是函數(shù)式編程,函數(shù)式編程又有什么優(yōu)點(diǎn),這就在這篇博客進(jìn)行一個簡單的總結(jié)吧~ 主要內(nèi)容: 函...
閱讀 3553·2021-09-10 10:51
閱讀 2524·2021-09-07 10:26
閱讀 2504·2021-09-03 10:41
閱讀 826·2019-08-30 15:56
閱讀 2919·2019-08-30 14:16
閱讀 3508·2019-08-30 13:53
閱讀 2122·2019-08-26 13:48
閱讀 1929·2019-08-26 13:37