搜尋
首頁web前端js教程使您的JavaScript更具功能性的5種方法

5 Ways to Make Your JavaScript More Functional

本文將簡要介紹函數式編程的概念,並闡述五種提升 JavaScript 代碼函數式風格的方法。

核心要點

  • 函數式編程是一種編程範式,它使用函數及其應用而非命令列表。它更抽象,起源於數學。 JavaScript 特別適合函數式編程,因為函數是第一類對象。
  • 純函數是函數式編程的關鍵部分。給定相同的參數,它們始終返回相同的值,並且不會更改函數作用域之外的內容。它們使您的代碼更易於移植和測試。
  • 在函數式編程中,變量應保持不變。設置變量後,它應在整個程序中保持該狀態。這可以通過始終使用 const 聲明變量來實現。
  • 建議在 JavaScript 的函數式編程中使用箭頭函數和三元運算符。箭頭函數具有隱式返回值,這有助於可視化輸入到輸出的映射。三元運算符是始終返回值的表達式,因此對於確保存在返回值很有用。
  • 應避免在函數式編程中使用 for 循環,因為它們依賴於可變狀態。應改用遞歸和高階數組方法。此外,應避免類型強制以保持類型一致性。這可以通過在聲明函數之前編寫類型聲明註釋來實現。

什麼是函數式編程?

函數式編程是一種編程範式,它使用函數及其應用,而不是在命令式編程語言中使用的命令列表。

這是一種更抽象的編程風格,其根源在於數學——特別是稱為 lambda 演算的數學分支,該分支由數學家 Alonzo Church 於 1936 年設計為可計算性的形式模型。它由表達式和函數組成,這些表達式和函數將一個表達式映射到另一個表達式。從根本上說,這就是我們在函數式編程中所做的:我們使用函數將值轉換為不同的值。

本文作者近年來愛上了函數式編程。我們開始使用鼓勵更函數式風格的 JavaScript 庫,然後通過學習如何在 Haskell 中編寫代碼直接跳入深水區。

Haskell 是一種純函數式編程語言,開發於 20 世紀 90 年代,類似於 Scala 和 Clojure。使用這些語言,您將被迫採用函數式風格進行編碼。學習 Haskell 使我們真正了解了函數式編程提供的所有優勢。

JavaScript 是一種多範式語言,因為它可以用於以命令式、面向對像或函數式風格進行編程。但是,它確實特別適合函數式風格,因為函數是第一類對象,這意味著它們可以賦值給變量。這也意味著函數可以作為參數傳遞給其他函數(通常稱為回調),也可以作為其他函數的返回值。返回其他函數或接受其他函數作為參數的函數稱為高階函數,它們是函數式編程的基礎部分。

近年來,以函數式風格編程 JavaScript 變得越來越流行,尤其是在 React 興起之後。 React 使用適合函數式方法的聲明式 API,因此紮實掌握函數式編程原理將改進您的 React 代碼。

為什麼函數式編程如此優秀?

簡而言之,函數式編程語言通常會導致代碼簡潔、清晰且優雅。代碼通常更容易測試,並且可以在多線程環境中運行而不會出現任何問題。

如果您與許多不同的程序員交談,您可能會從每個人那裡獲得關於函數式編程的完全不同的意見——從那些絕對討厭它的人到那些絕對喜歡它的人。我們(本文作者)站在“喜歡它”的一端,但我們完全理解它並非每個人的菜,尤其因為它與通常教授的編程方式大相徑庭。

但是,一旦您掌握了函數式編程,並且一旦思維過程點擊到位,它就會成為第二天性,並改變您編寫代碼的方式。

規則 1:淨化您的函數

函數式編程的關鍵部分是確保您編寫的函數是“純”的。如果您不熟悉這個術語,純函數基本上滿足以下條件:

  • 它具有引用透明性。這意味著,給定相同的參數,函數將始終返回相同的值。任何函數調用都可以用返回值替換,程序仍然會以相同的方式運行。
  • 它沒有副作用。這意味著函數不會在函數作用域之外進行任何更改。這可能包括更改全局值、記錄到控制台或更新 DOM。

純函數必須至少有一個參數,並且必須返回值。如果您仔細考慮,如果它們不接受任何參數,它們將沒有任何數據可以使用,如果它們不返回值,那麼函數的意義何在?

純函數一開始可能看起來並非完全必要,但使用不純函數會導致程序發生整體變化,從而導致一些嚴重的邏輯錯誤!

例如:

// 不纯
let minimum = 21;
const checkAge = (age) => age >= minimum;

// 纯
const checkAge = (age) => {
    const minimum = 21;
    return age >= minimum;
};

在不純函數中,checkAge 函數依賴於可變變量 minimum。例如,如果稍後在程序中更新 minimum 變量,則 checkAge 函數可能會使用相同的輸入返回布爾值。

假設我們運行以下代碼:

checkAge(20); // false

現在,假設稍後在代碼中,changeToUK() 函數將 minimum 的值更新為 18。

然後,假設我們運行以下代碼:

// 不纯
let minimum = 21;
const checkAge = (age) => age >= minimum;

// 纯
const checkAge = (age) => {
    const minimum = 21;
    return age >= minimum;
};

現在,checkAge 函數評估為不同的值,儘管給出了相同的輸入。

純函數使您的代碼更易於移植,因為它們不依賴於作為參數提供的任何值之外的任何其他值。返回值永遠不會改變的事實使純函數更容易測試。

一致地編寫純函數還可以消除發生突變和副作用的可能性。

突變是函數式編程中的一大危險信號,如果您想了解更多信息,可以閱讀關於它們在《JavaScript 中變量賦值和突變指南》中的內容。

為了使您的函數更易於移植,請確保您的函數始終保持純淨。

規則 2:保持變量不變

聲明變量是任何程序員學習的第一件事之一。它變得微不足道,但在使用函數式編程風格時卻極其重要。

函數式編程的關鍵原則之一是,一旦設置了變量,它就會在整個程序中保持該狀態。

這是顯示代碼中變量的重新賦值/重新聲明如何成為災難的最簡單的示例:

checkAge(20); // false

如果您仔細考慮,n 的值不可能同時為 10 和 11;這在邏輯上說不通。

命令式編程中的一種常見編碼實踐是使用以下代碼遞增值:

checkAge(20); // true

在數學中,語句 x = x 1 是不合邏輯的,因為如果您從兩邊減去 x,您將得到 0 = 1,這顯然是不正確的。

因此,在 Haskell 中,您不能將變量賦值給一個值,然後將其重新賦值給另一個值。為了在 JavaScript 中實現這一點,您應該遵循始終使用 const 聲明變量的規則。

規則 3:使用箭頭函數

在數學中,函數的概念是將一組值映射到另一組值的概念。下圖顯示了通過平方將左側的值集映射到右側的值集的函數:

5 Ways to Make Your JavaScript More Functional

這就是使用箭頭表示法在數學中編寫它的方式:f: x → x²。這意味著函數 f 將值 x 映射到 x²。

我們可以使用箭頭函數幾乎以相同的方式編寫此函數:

const n = 10;
n = 11; // TypeError: "Attempted to assign to readonly property."

在 JavaScript 中使用函數式風格的一個關鍵特徵是使用箭頭函數而不是常規函數。當然,這確實歸結為風格,使用箭頭函數而不是常規函數實際上不會影響代碼的“函數式”程度。

但是,在使用函數式編程風格時,最難適應的事情之一是將每個函數都視為輸入到輸出的映射的思維方式。沒有所謂的過程。我們發現使用箭頭函數可以幫助我們更好地理解函數的過程。

箭頭函數具有隱式返回值,這確實有助於可視化此映射。

箭頭函數的結構——尤其是它們的隱式返回值——有助於鼓勵編寫純函數,因為它們的結構實際上是“輸入映射到輸出”:

// 不纯
let minimum = 21;
const checkAge = (age) => age >= minimum;

// 纯
const checkAge = (age) => {
    const minimum = 21;
    return age >= minimum;
};

另一件事是我們喜歡強調的,尤其是在編寫箭頭函數時,是使用三元運算符。如果您不熟悉三元運算符,它們是內聯 if...else 語句,形式為 condition ? value if true : value if false

您可以閱讀更多關於它們在《快速提示:如何在 JavaScript 中使用三元運算符》中的內容。

在函數式編程中使用三元運算符的主要原因之一是 else 語句的必要性。程序必須知道如果不滿足原始條件該怎麼做。例如,Haskell 會強制執行 else 語句,如果沒有給出 else 語句,它將返回錯誤。

使用三元運算符的另一個原因是它們是始終返回值的表達式,而不是可以用於執行可能具有副作用的操作的 if-else 語句。這對於箭頭函數特別有用,因為它意味著您可以確保存在返回值並保持輸入到輸出映射的圖像。如果您不確定語句和表達式之間的細微差別,那麼關於語句與表達式的指南非常值得一讀。

為了說明這兩個條件,以下是一個使用三元運算符的簡單箭頭函數示例:

checkAge(20); // false

action 函數將根據 state 參數的值返回“eat”或“sleep”的值。

因此,總之:在使您的代碼更具函數式時,您應該遵循以下兩條規則:

  • 使用箭頭表示法編寫函數
  • if...else 語句替換為三元運算符

規則 4:刪除 for 循環

鑑於使用 for 循環編寫迭代代碼在編程中非常常見,說要避免它們似乎很奇怪。事實上,當我們第一次發現 Haskell 甚至沒有任何類型的 for 循環操作時,我們難以理解如何實現某些標準操作。但是,有一些非常好的理由說明為什麼 for 循環不會出現在函數式編程中,我們很快發現每種類型的迭代過程都可以在不使用 for 循環的情況下實現。

不使用 for 循環最重要的原因是它們依賴於可變狀態。讓我們來看一個簡單的求和函數:

checkAge(20); // true

如您所見,我們必須在 for 循環本身以及我們在 for 循環中更新的變量中使用 let

如前所述,這通常是函數式編程中的不良做法,因為函數式編程中的所有變量都應該是不可變的。

如果我們想編寫所有變量都是不可變的代碼,我們可以使用遞歸:

const n = 10;
n = 11; // TypeError: "Attempted to assign to readonly property."

如您所見,沒有變量被更新。

我們當中的數學家顯然會知道所有這些代碼都是不必要的,因為我們可以只使用巧妙的求和公式 0.5*n*(n 1)。但這是一種很好的方法,可以說明 for 循環的可變性與遞歸之間的區別。

但是,遞歸併不是解決可變性問題的唯一解決方案,尤其是在處理數組時。 JavaScript 具有許多內置的高階數組方法,這些方法可以遍歷數組中的值而無需更改任何變量。

例如,假設我們要將 1 加到數組中的每個值。使用命令式方法和 for 循環,我們的函數可能如下所示:

// 不纯
let minimum = 21;
const checkAge = (age) => age >= minimum;

// 纯
const checkAge = (age) => {
    const minimum = 21;
    return age >= minimum;
};

但是,我們可以使用 JavaScript 的內置 map 方法並編寫如下所示的函數:

checkAge(20); // false

如果您以前從未見過map 函數,那麼絕對值得了解它們——以及JavaScript 的所有內置高階數組方法,例如filter,尤其如果您真的對JavaScript 中的函數式編程感興趣。您可以在《不可變數組方法:如何編寫非常清晰的 JavaScript 代碼》中找到更多關於它們的信息。

Haskell 完全沒有 for 循環。為了使您的 JavaScript 更具函數式,請嘗試通過使用遞歸和內置的高階數組方法來避免使用 for 循環。

規則 5:避免類型強制

在使用 JavaScript 等不需要類型聲明的語言進行編程時,很容易忘記數據類型的重要性。 JavaScript 中使用的七種原始數據類型是:

  • Number
  • String
  • Boolean
  • Symbol
  • BigInt
  • Undefined
  • Null

Haskell 是一種強類型語言,需要類型聲明。這意味著在任何函數之前,您都需要使用 Hindley-Milner 系統指定進入的數據類型和輸出的數據類型。

例如:

checkAge(20); // true

這是一個非常簡單的函數,它將兩個數字(x 和 y)加在一起。對於每個函數,包括像這樣的非常簡單的函數,都必須向程序解釋數據類型似乎有點荒謬,但這最終有助於顯示函數的預期工作方式及其預期返回的內容。這使得代碼更容易調試,尤其是在代碼變得更複雜時。

類型聲明遵循以下結構:

const n = 10;
n = 11; // TypeError: "Attempted to assign to readonly property."

類型強制在使用 JavaScript 時可能是一個大問題,JavaScript 具有各種可以用來(甚至濫用)繞過數據類型不一致的技巧。以下是最常見的技巧以及如何避免它們:

  • 連接。 “Hello” 5 評估為“Hello5”,這並不一致。如果您想將字符串與數值連接起來,您應該編寫“Hello” String(5)。
  • 布爾語句和 0。在 JavaScript 中,if 語句中的 0 值等效於 false。這可能導致懶惰的編程技術,忽略檢查數值數據是否等於 0。

例如:

// 不纯
let minimum = 21;
const checkAge = (age) => age >= minimum;

// 纯
const checkAge = (age) => {
    const minimum = 21;
    return age >= minimum;
};

這是一個評估數字是否為偶數的函數。它使用 ! 符號將 n % 2 的結果強制轉換為布爾值,但 n % 2 的結果不是布爾值,而是一個數字(0 或 1)。

像這樣的技巧,雖然看起來很聰明,並且減少了您編寫的代碼量,但它們破壞了函數式編程的類型一致性規則。因此,編寫此函數的最佳方法如下所示:

checkAge(20); // false

另一個重要概念是確保數組中的所有數據值都是相同類型。 JavaScript 不會強制執行此操作,但如果沒有相同類型,當您想要使用高階數組方法時可能會導致問題。

例如,一個將數組中所有數字相乘並返回結果的乘積函數可以用以下類型聲明註釋編寫:

checkAge(20); // true

在這裡,類型聲明清楚地表明函數的輸入是一個包含 Number 類型元素的數組,但它只返回一個數字。類型聲明清楚地說明了此函數的預期輸入和輸出。顯然,如果數組不只包含數字,則此函數將無法工作。

Haskell 是一種強類型語言,而 JavaScript 是一種弱類型語言,但為了使您的 JavaScript 更具函數式,您應該在聲明函數之前編寫類型聲明註釋,並確保避免類型強制快捷方式。

我們還應該在這裡提到,如果您想要 JavaScript 的強類型替代方案,該替代方案將為您強制執行類型一致性,那麼您可以轉向 TypeScript。

結論

總而言之,以下五個規則將幫助您實現函數式代碼:

  • 保持您的函數純淨
  • 始終使用const聲明變量和函數。
  • 對函數使用箭頭表示法。
  • 避免使用 for 循環
  • 使用類型聲明註釋並避免類型強制快捷方式。

雖然這些規則不能保證您的代碼是純函數式的,但它們將在很大程度上使其更具函數式,並有助於使其更簡潔、更清晰且更容易測試。

我們真的希望這些規則能像幫助我們一樣幫助您!我們兩人都是函數式編程的忠實粉絲,我們強烈建議任何程序員使用它。

如果您想進一步深入研究函數式 JavaScript,我們強烈建議您閱讀《弗里斯比教授關於函數式編程的大部分充分指南》,該指南可以在線免費獲取。如果您想全力以赴學習 Haskell,我們建議您使用 Try Haskell 交互式教程並閱讀優秀的《學習 Haskell 以獲得更大的好處》一書,該書也可以在線免費閱讀。

關於 JavaScript 函數式編程的常見問題

什麼是 JavaScript 中的函數式編程? 函數式編程是一種編程範式,它將計算視為數學函數的評估,並避免更改狀態和可變數據。在 JavaScript 中,它涉及使用函數作為一等公民並避免副作用。

什麼是 JavaScript 中的一等函數? JavaScript 中的一等函數意味著函數被視為與任何其他變量一樣。它們可以賦值給變量,作為參數傳遞給其他函數,並作為值從其他函數返回。

什麼是函數式編程中的不變性? 不變性是指一旦創建對象,就不能更改它。在 JavaScript 函數式編程的上下文中,這意味著在初始化變量或數據結構後避免修改它們。

什麼是高階函數? 高階函數是將其他函數作為參數或返回函數作為結果的函數。它們支持函數的組合,使創建模塊化和可重用代碼更容易。

是否有任何庫/框架可以促進 JavaScript 中的函數式編程? 是的,一些庫和框架(例如 Ramda 和 lodash)提供了支持 JavaScript 函數式編程概念的實用程序和函數。它們可以幫助簡化和增強函數式編程實踐。

以上是使您的JavaScript更具功能性的5種方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Python vs. JavaScript:學習曲線和易用性Python vs. JavaScript:學習曲線和易用性Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python vs. JavaScript:社區,圖書館和資源Python vs. JavaScript:社區,圖書館和資源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C到JavaScript:所有工作方式從C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

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實現跨平台開發,提高開發效率。

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.能量晶體解釋及其做什麼(黃色晶體)
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

Safe Exam Browser

Safe Exam Browser

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

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

PhpStorm Mac 版本

PhpStorm Mac 版本

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