一装诡、定義:函數(shù)式編程就是一種“編程范式”叽赊,也就是如何編寫程序的方法論。
舉例: (1+2)* 3 - 4
傳統(tǒng)的過程式編程會(huì)是這樣的 var a = 1+2;
? ??????????????????????????????????????????????var b = a*3;
? ? ?????????????????????????????????????????????var c = b-4;
函數(shù)式編程會(huì)是這樣的 var result = subtract ( multiply ( add ( 1, 2 ) , 3 ) , 4 )
二掸驱、函數(shù)式編程的特點(diǎn)
1朱监、函數(shù)是“第一等公民”? ? ?
????????所謂“第一等公民”指的是函數(shù)與其他數(shù)據(jù)類型一樣,處于平等的地位蛇捌,可以賦值給其他變量抚恒,也可以作為參數(shù),傳入給另外一個(gè)函數(shù)络拌,或者作為別人函數(shù)的返回值俭驮。? ? ? ? ????????舉例來說,下面的代碼中print變量就是春贸,一個(gè)函數(shù)可以作為另一個(gè)函數(shù)的參數(shù)混萝。
var print = function( i ) {
console.log( i );
};
[1, 2, 3].forEach(print);
2、只用“表達(dá)式”萍恕,不用“語句”
? ? ?“表達(dá)式”(expression)是一個(gè)單純的運(yùn)算過程逸嘀,總是有返回值;“語句“(statement)是執(zhí)行某種操作允粤,沒有返回值崭倘。函數(shù)式編程要求,只使用表達(dá)式类垫,不使用語句绳姨。也就是說,每一步都是單純的元算阔挠,而且沒有返回值飘庄。 ? ? ?????
? ? ? ?原因是函數(shù)式編程的開發(fā)動(dòng)機(jī),一開始就是為了處理運(yùn)算的购撼,不考慮系統(tǒng)的讀寫(I/O)跪削。“語句”屬于對(duì)系統(tǒng)的讀寫操作迂求,所以就被排斥在外碾盐。
? ? ? ?當(dāng)然,實(shí)際應(yīng)用中揩局,不做I/O是不可能的毫玖。因此,編程過程中,函數(shù)式編程只要求把I/O限制到最小付枫,不要有不必要的讀寫行為烹玉,保持計(jì)算過程的單純性。
3阐滩、沒有“副作用” ? ? ? ?
????????所謂“副作用”二打,指的是函數(shù)內(nèi)部與外部互動(dòng)(最典型的情況,就是修改全局變量的值)掂榔,產(chǎn)生運(yùn)算意外的其他結(jié)果继效。 ? ? ?
?????????函數(shù)式編程強(qiáng)調(diào)沒有“副作用”,意味著函數(shù)要保持獨(dú)立装获,所有功能就是返回一個(gè)新的值瑞信,沒有其他行為,尤其是不得修改外部 變量的值穴豫。
4凡简、不修改狀態(tài) ? ? ? ?
????????上一點(diǎn)已經(jīng)提到過,函數(shù)式編程只是返回新的值绩郎,不修改系統(tǒng)變量潘鲫。因此,不修改變量肋杖,也是它的一個(gè)重要特點(diǎn)溉仑。 ? ? ? ?
????????在其他類型的語言中,變量往往用來保存“狀態(tài)”状植。不修改變量浊竟,意味著狀態(tài)不能保存在變量中。函數(shù)式編程使用參數(shù)保存狀態(tài)津畸,最好的例子就是遞歸振定。下面的代碼是一個(gè)將字符串逆序排列的函數(shù),它演示了不同的參數(shù)如何決定了運(yùn)算所處的“狀態(tài)”肉拓。
function reverse(string) {
? ? ? ? ?if (string.length == 0) {
? ? ? ? ? ? ? ?return string; ? ? ?
} else {
? ? ? ? ? ? ? ? return reverse(string.substring(1, string.length)) + string.substring(0, 1);
? ? ?}
}
由于使用了遞歸后频,函數(shù)式語言的運(yùn)行速度比較慢,這事它長(zhǎng)期不能在業(yè)界推廣的主要原因暖途。
5卑惜、引用透明 ? ? ?
????????引用透明,指的是函數(shù)的運(yùn)行不依賴于外部變量或“狀態(tài)”驻售,只依賴于輸入的參數(shù)露久,任何時(shí)候只要參數(shù)相同,引用函數(shù)所得到的返回值總是相同的欺栗。 ? ? ?
????????有了前面的第三點(diǎn)和第四點(diǎn)毫痕,這點(diǎn)是很顯然的征峦。其他類型的語言,函數(shù)的返回值汪汪與系統(tǒng)狀態(tài)有關(guān)消请,不同的狀態(tài)之下栏笆,返回值是不一樣的。這就叫“引用不透明”梯啤,很不利于觀察和理解程序的行為竖伯。
三存哲、意義
函數(shù)式編程到底有什么好處因宇,為什么會(huì)變得越來越流行?
????????1祟偷、代碼簡(jiǎn)潔察滑,開發(fā)快速 ? ? 函數(shù)式編程大量使用函數(shù),減少了代碼的重復(fù)修肠,因此程序比較短贺辰,開發(fā)速度較快。
? ? ? ? 2嵌施、接近自然語言饲化,易于理解 ? ? ?函數(shù)式編程的自由度很高,可以寫出很接近自然語言的代碼吗伤。
????????3吃靠、更方便的代碼管理 ? ? ?函數(shù)式編程不依賴、也不會(huì)改變外界的狀態(tài)足淆,只要給定輸入?yún)?shù)巢块,返回的結(jié)果必定相同。因此巧号,每一個(gè)函數(shù)都可以被看做獨(dú)立單元族奢,很有利于進(jìn)行單元測(cè)試和除錯(cuò),以及模塊化組合丹鸿。
????????4越走、易于“并發(fā)編程” ? ? 函數(shù)式編程不需要考慮“死鎖”,因?yàn)樗恍薷淖兞靠炕叮愿静淮嬖凇版i”線程的問題廊敌。不必?fù)?dān)心一個(gè)線程的數(shù)據(jù),被另一個(gè)線程修改掺涛,所以可以很放心地把工作分?jǐn)偟蕉鄠€(gè)線程庭敦,部署“并發(fā)編程”。
????????5薪缆、代碼的熱升級(jí) ? ? 函數(shù)式編程沒有副作用秧廉,只要保證接口不變伞广,內(nèi)部實(shí)現(xiàn)是外部無關(guān)的。所以疼电,可以在運(yùn)行狀態(tài)下直接升級(jí)代碼嚼锄,不需要重啟,也不需要停機(jī)蔽豺。