搜尋
首頁web前端js教程Javascript函數式程式語言_javascript技巧

函數式程式語言

函數式程式語言是那些方便使用函數式程式設計範式的語言。簡單來說,如果具備函數式程式設計所需的特徵, 它就可以稱為函數式語言。在多數情況下,程式設計的風格實際上決定了一個程式是否是函數式的。

是什麼讓一個語言具有函數式特徵?

函數式程式設計無法用C語言來實現。函數式程式設計也無法用Java來實現(不包括那些透過大量變通手段實現的近似函數式程式設計)。 這些語言不包含支援函數式程式設計的結構。他們是純粹物件導向的、嚴格非函數式的語言。

同時,純函數語言也無法使用物件導向編程,例如Scheme、Haskell以及Lisp。

然而有些語言兩種模式都支援。 Python是個著名的例子,不過還有別的:Ruby,Julia,以及我們最感興趣的Javascript。 這些語言是如何支援這兩種差異如此之大的設計模式呢?它們包含兩種程式設計範式所需的特徵。 然而對Javascript來說,函數式的特徵似乎是被隱藏了。

但實際上,函數式語言所需要的比上述要多一些。到底函數式語言有什麼特徵呢?

特点 命令式 函数式
编程风格 一步一步地执行,并且要管理状态的变化 描述问题和和所需的数据变化以解决问题
状态变化 很重要 不存在
执行顺序 很重要 不太重要
主要的控制流 循环、条件、函数调用 函数调用和递归
主要的操作单元 结构体和类对象 函数作为一等公民的对象和数据集

函數式語言的語法必須顧及到特定的設計模式,例如類型推斷系統和匿名函數。大體上,這個語言必須實現lambda演算。 而解釋器的求值策略必須是非嚴格、按需調用的(也稱為延遲執行),它允許不變資料結構和非嚴格、惰性求值。

译注:这一段用了一些函数式编程的专业词汇。lambda演算是一套函数推演的形式化系统(听起来很晕), 它的先决条件是内部函数和匿名函数。非严格求值和惰性求值差不多一个意思,就是并非严格地按照运算规则把所有元素先计算一遍, 而是根据最终的需求只计算有用的那一部分,比如我们要取有一百个元素的数组的前三项, 那惰性求值实际只会计算出一个具有三个元素是数组,而不会先去计算那个一百个元素的数组。 

優點

當你最終掌握了函數式程式設計它將給你巨大的啟蒙。這樣的經驗會讓你後面的程式設計師生涯更上一個台階, 無論你是否真的會成為一個全職的函數式程式設計師。

不過我們現在不是在討論如何去學習冥想;我們正在探討如何去學習一個非常有用的工具,它將會讓你成為一個更好的程式設計師。

總的來說,什麼是使用函數式程式設計真正實際的優點呢?

更簡潔的程式碼

函數式程式設計更簡潔、更簡單、更小。它簡化了調試、測試和維護。

例如,我們需要這樣一個函數,它能將二維數組轉換為一維數組。如果只用命令式的技術,我們會寫成這樣:

function merge2dArrayIntoOne(arrays) {
  var count = arrays.length;
  var merged = new Array(count);
  var c = 0;
  for (var i = 0; i < count; ++i) {
   for (var j = 0, jlen = arrays[i].length; j < jlen; ++j) {
    merged[c++] = arrays[i][j];
   }
  }
  return merged
}

現在使用函數式技術,可以寫成這樣:

merge2dArrayIntoOne2 = (arrays) ->
 arrays.reduce (memo, item) ->
  memo.concat item
 , []
var merge2dArrayIntoOne2 = function(arrays) {
 return arrays.reduce( function(p,n){
  return p.concat(n);
 }, []);
};

译注:原著中代码有误,调用reduce函数时少了第二个参数空数组,这里已经补上。

這兩個函數有相同的輸入並傳回相同的輸出,但是函數式的範例更簡潔。

模組化

函數式程式設計強制把大型問題拆分成解決同樣問題的更小的情形,這就意味著程式碼會更加模組化。 模組化的程式有更清晰的描述,更容易調試,維護起來也更簡單。測試也會變得更加容易, 這是由於每個模組的程式碼都可以單獨檢測正確性。

多用性

由於其模組化的特性,函數式程式設計會有許多通用的輔助函數。你將會發現這裡面的許多函數可以在大量不同的應用中重複使用。

在後面的章節裡,許多最通用的函數將會被覆蓋到。然而,作為一個函數式程式設計師,你將不可避免地編寫自己的函數庫, 這些函數會被一次又一次地使用。例如一個用於在行間尋找設定檔的函數,如果設計好了也可以用來尋找Hash表。

減少耦合

耦合是程式裡模組間的大量相依性。由於函數式程式設計遵循編寫一等公民的、高階的純函數, 這使得它們對全域變數沒有副作用而彼此完全獨立,耦合極大程度上的減小了。 當然,函數會不可避免地相互依賴,但是改變一個函數不會影響其他的,只要輸入和輸出的一對一映射保持正確。

數學正確性

最後一點更理論一些。由於根植於lambda演算,函數式程式設計可以在數學上證明正確性。 這對一些研究者來說是一個巨大的優點,他們需要用程式來證明成長率、時間複雜度以及數學正確性。

我們來看看斐波那契數列。儘管它很少用於概念性證明以外的問題,但是用它來解釋這個概念非常好。 對一個斐波那契數列求值標準的方法是建立一個遞歸函數,像這樣:

fibonnaci(n) = fibonnaci(n-2) + fibonnaci(n–1) 

還要加上一個一般情形:

return 1 when n < 2

這使得遞歸可以終止,並且讓遞歸呼叫堆疊裡的每一步從這裡開始累加。

以下列出詳細步驟

var fibonacci = function(n) {
 if (n < 2) {
  return 1; 
 }else {
  return fibonacci(n - 2) + fibonacci(n - 1);
 } 
}
console.log( fibonacci(8) );
// Output: 34

然而,在一個懶執行函數庫的輔助下,可以產生一個無窮大的序列,它是透過數學方程式來定義整個序列的成員的。 只有那些我們最終需要的成員最後才會被計算出來。

var fibonacci2 = Lazy.generate(function() {
 var x = 1,
 y = 1;
 return function() {
  var prev = x;
  x = y;
  y += prev;
  return prev;
 }; 
}());
console.log(fibonacci2.length());
// Output: undefined
console.log(fibonacci2.take(12).toArray());
// Output: [1, 1, 2, 3, 5,8, 13, 21, 34, 55, 89, 144]
var fibonacci3 = Lazy.generate(function() {
 var x = 1,
 y = 1;
 return function() {
  var prev = x;
  x = y;
  y += prev;
  return prev;
 }; 
}());
console.log(fibonacci3.take(9).reverse().first(1).toArray());
//Output: [34]

第二个例子明显更有数学的味道。它依赖Lazy.js函数库。还有一些其它这样的库,比如Sloth.js、wu.js, 这些将在第三章里面讲到。

我插几句:后面这个懒执行的例子放这似乎仅仅是来秀一下函数式编程在数学正确性上的表现。 更让人奇怪的是作者还要把具有相同内部函数的懒加载写两遍,完全没意义啊…… 我觉得各位看官知道这是个懒执就行了,不必深究。

非函数式世界中的函数式编程

函数式和非函数式编程能混合在一起吗?尽管这是第七章的主题,但是在我们进一步学习之前, 还是要弄明白一些东西。

这本书并没要想要教你如何严格地用纯函数编程来实现整个应用。这样的应用在学术界之外不太适合。 相反,这本书是要教你如何在必要的命令式代码之上使用纯函数的设计策略。

例如,你需要在一段文本中找出头四个只含有字母的单词,稚嫩一些的写法会是这样:

var words = [], count = 0;
text = myString.split(' ');
for (i=0; count < 4, i < text.length; i++) {
 if (!text[i].match(/[0-9]/)) {
  words = words.concat(text[i]);
  count++;
 } 
}
console.log(words);

函数式编程会写成这样:

var words = [];
var words = myString.split(' ').filter(function(x){
 return (! x.match(/[1-9]+/));
}).slice(0,4);
console.log(words);

如果有一个函数式编程的工具库,代码可以进一步被简化:

复制代码 代码如下:

var words = toSequence(myString).match(/[a-zA-Z]+/).first(4);

判斷一個函數是否能被寫成更函數式的方式是尋找循環和臨時變量,例如前面例子裡面的「words」和」count」變數。 我們通常可以用高階函數來取代迴圈和臨時變量,本章後面的部分將繼續探索。

Javascript是函數式程式語言嗎?

現在還有最後一個問題我們需要問自己,Javascript是函數式語言還是非函數式語言?

Javascript可以說是世界上最流行卻最沒有被理解的函數式程式語言。 Javascript是一種披著C外衣的函數式程式語言。 它的語法無疑和C比較像,這意味著它使用C語言的塊式語法和中綴語序。而且它是現存語言中名字起得最差勁的。 你不用去想像就可以看出來有多少人會因為Javascript和Java的關係而迷惑,就好像它的名字暗示了它會是什麼樣的東西! 但其實它和Java的共同點非常少。不過還真有一些要把Javascript強制弄成物件導向語言的主意, 例如Dojo、ease.js這些函式庫曾做了大量工作試圖抽象Javascript以使其適合物件導向程式設計。 Javascript來自於90年代那個滿世界都嚷嚷著物件導向的時代,我們被告知Javascript是一個物件導向語言是因為我們希望它是這樣, 但實際上它不是。

它的真實身分可以追溯到它的原型:Scheme和Lisp,兩個經典的函數式程式語言。 Javascript一直都是函數式程式語言。 它的函數是頭等公民,並且可以嵌套,它具有閉包和複合函數,它允許珂理化和monad。所有這些都是函數式程式設計的關鍵。 這裡另外還有一些Javascript是函數式語言的原因:

• Javascript的詞法包括了傳遞函數為參數的能力,具有類型推斷系統,支援匿名函數、高階函數、閉包等等。 這些特點對構成函數式程式設計的結構和行為至關重要。

• Javascript不是純粹物件導向語言,它的多數物件導向設計模式都是透過拷貝Prototype物件來完成的, 這是一個弱物件導向程式設計的模型。歐洲電腦製造商協會腳本(ECMAScript)-Javascript的正式形式與標準實作 -在4.2.1版本的規格裡有以下陳述:
「Javascript不具有像C 、Smalltalk、Java那樣的真正的類,但是支援創建物件的建構器。 一般來說,在基於類別的物件導向語言裡,狀態由實例承載,方法由類別承載,繼承只是針對結構和行為。

• Javascript是一種解釋型語言。 Javascript的解譯器(有時被稱為「引擎」)非常類似於Scheme的解譯器。 它們都是動態的,都有易於組合和傳輸的靈活的資料類型,都把程式碼求值為表達式區塊,處理函數的方式也類似。

也就是說,Javascript的確不是一個純函數式語言。它缺乏惰性求值和內建的不可變數據。 這是由於大多數解釋器是按名調用,而不是按需調用。 Javascript由於其尾呼叫的處理方式也不太善於處理遞迴。 不過所有的這些問題都可以透過一些小小的注意事項來緩和。需要無窮序列和惰性求值的非嚴格求值可以透過一個叫Lazy.js的函式庫來實現。 不可變數只需要簡單的透過程式設計技巧就可以實現,不過它不是透過依賴語言層面來限製而是需要程式設計師自律。 尾遞歸消除可以透過一個叫Trampolining的方法來實現。這些問題將在第六章講解。

關於Javascript是函數式語言還是物件導向語言還是兩者皆是還是兩者皆非的爭論一直都很多,而且這些爭論還要繼續下去。

最後,函數式程式設計是透過巧妙的變化、組合、使用函數而實現編寫簡潔程式碼的方式。而Javascript為實現這些提供了很好的途徑。 如果你真要挖掘出Javascript全部的潛能,你必須學會如何將它當作函數式語言來使用。


陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的演變:當前的趨勢和未來前景JavaScript的演變:當前的趨勢和未來前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

神秘的JavaScript:它的作用以及為什麼重要神秘的JavaScript:它的作用以及為什麼重要Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python還是JavaScript更好?Python還是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

如何安裝JavaScript?如何安裝JavaScript?Apr 05, 2025 am 12:16 AM

JavaScript不需要安裝,因為它已內置於現代瀏覽器中。你只需文本編輯器和瀏覽器即可開始使用。 1)在瀏覽器環境中,通過標籤嵌入HTML文件中運行。 2)在Node.js環境中,下載並安裝Node.js後,通過命令行運行JavaScript文件。

在Quartz中如何在任務開始前發送通知?在Quartz中如何在任務開始前發送通知?Apr 04, 2025 pm 09:24 PM

如何在Quartz中提前發送任務通知在使用Quartz定時器進行任務調度時,任務的執行時間是由cron表達式設定的。現�...

在JavaScript中,如何在構造函數中獲取原型鏈上函數的參數?在JavaScript中,如何在構造函數中獲取原型鏈上函數的參數?Apr 04, 2025 pm 09:21 PM

在JavaScript中如何獲取原型鏈上函數的參數在JavaScript編程中,理解和操作原型鏈上的函數參數是常見且重要的任�...

微信小程序webview中Vue.js動態style位移失效是什麼原因?微信小程序webview中Vue.js動態style位移失效是什麼原因?Apr 04, 2025 pm 09:18 PM

在微信小程序web-view中使用Vue.js動態style位移失效的原因分析在使用Vue.js...

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具