搜尋
首頁web前端js教程功能組成:可維護代碼的構建塊

Function Composition: Building Blocks for Maintainable Code

JavaScript 函數組合:構建更易維護的代碼

JavaScript 函數組合是一種將多個簡單函數組合成單個更複雜函數的技術,這些函數按邏輯順序對給定數據執行子函數操作。函數應用的順序會產生不同的結果。

為了編寫可維護的代碼,理解每個被組合函數的返回類型至關重要,以確保下一個函數可以正確處理它。 JavaScript 不會阻止組合返回不合適類型函數,因此這部分責任落在程序員身上。

對不熟悉函數式編程範式的人來說,組合函數可能會使代碼看起來很複雜。但是,隨著 ES2015 語法的出現,使用箭頭函數,可以一行代碼創建簡單的組合函數,而無需特殊的組合方法。

組合函數應該是純函數,這意味著每次將特定值傳遞給函數時,函數都應返回相同的結果,並且函數不應產生改變自身外部值的副作用。這將產生更簡潔、更易讀的代碼。

本文由 Jeff Mott、Dan Prince 和 Sebastian Seitz 共同評審。感謝所有 SitePoint 的同行評審者,使 SitePoint 的內容達到最佳狀態!

Function Composition: Building Blocks for Maintainable Code

函數式思維的優勢之一是能夠使用小型、易於理解的單個函數來構建複雜的功能。 但有時這需要反向思考問題,而不是正向思考,以便找出如何創建最優雅的解決方案。在本文中,我將採用循序漸進的方法來檢查 JavaScript 中的函數組合,並演示它如何產生更易於理解且錯誤更少的代碼。

嵌套函數

組合是一種技術,它允許你將兩個或多個簡單函數組合成一個更複雜的函數,該函數按邏輯順序對傳入的任何數據執行每個子函數。要獲得此結果,你需要將一個函數嵌套在另一個函數中,並對內部函數的結果重複執行外部函數的操作,直到產生結果。並且結果可能因函數應用的順序而異。這可以使用我們已經在 JavaScript 中熟悉的編程技術輕鬆演示,方法是將函數調用作為參數傳遞給另一個函數:

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
console.log(addOne(timesTwo(3))); //7
console.log(timesTwo(addOne(3))); //8

在這種情況下,我們定義了一個 addOne() 函數來為一個值加 1,以及一個 timesTwo() 函數將一個值乘以 2。通過將一個函數的結果作為另一個函數的參數傳入,我們可以看到如何將其中一個嵌套在另一個中會產生不同的結果,即使初始值相同也是如此。內部函數先執行,然後結果傳遞給外部函數。

命令式組合

如果你想重複執行相同的操作序列,定義一個新函數來自動應用第一個函數和第二個函數可能會很方便。這可能看起來像這樣:

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
console.log(addOne(timesTwo(3))); //7
console.log(timesTwo(addOne(3))); //8

在這種情況下,我們手動將這兩個函數按特定順序組合在一起。我們創建了一個新函數,該函數首先將傳遞的值分配給 holder 變量,然後通過執行第一個函數,然後是第二個函數來更新該變量的值,最後返回該 holder 的值。 (請注意,我們使用名為holder 的變量來臨時保存我們傳入的值。對於這樣一個簡單的函數,額外的局部變量似乎是多餘的,但即使在命令式JavaScript 中,將傳入函數的參數值視為常量也是一個好習慣。局部修改它們是可能的,但這會造成關於在函數的不同階段調用時參數值是什麼的混淆。)類似地,如果我們想創建一個另一個新函數以相反的順序應用這兩個較小的函數,我們可以執行以下操作:

// ...来自上面的先前函数定义
function addOneTimesTwo(x) {
  var holder = x;
  holder = addOne(holder);
  holder = timesTwo(holder);
  return holder;
}
console.log(addOneTimesTwo(3)); //8
console.log(addOneTimesTwo(4)); //10

當然,這段代碼開始看起來非常重複。我們的兩個新的組合函數幾乎完全相同,只是它們調用的兩個較小函數的執行順序不同。我們需要簡化它(就像不要重複自己一樣)。此外,使用像這樣改變其值的臨時變量並不是很函數式,即使它隱藏在我們正在創建的組合函數內部也是如此。底線:我們可以做得更好。

創建函數式組合

讓我們創建一個組合函數,它可以採用現有的函數並將它們按我們想要的順序組合在一起。為了以一致的方式做到這一點,而無需每次都處理內部細節,我們必須決定要將函數作為參數傳入的順序。我們有兩個選擇。參數將分別是函數,它們可以從左到右或從右到左執行。也就是說,使用我們提出的新函數,compose(timesTwo, addOne) 可以表示 timesTwo(addOne()) 從右到左讀取參數,或者 addOne(timesTwo()) 從左到右讀取參數。從左到右執行參數的優點是它們將以英語相同的閱讀方式讀取,這與我們命名組合函數 timesTwoAddOne() 以暗示乘法應在加法之前發生的方式非常相似。我們都知道邏輯命名對於簡潔易讀的代碼的重要性。從左到右執行參數的缺點是待操作的值必須放在前面。但是,將值放在前面使得將來用其他函數組合結果函數不太方便。為了很好地解釋這種邏輯背後的思想,你無法超越 Brian Lonsdorf 的經典視頻 Hey Underscore, You’re Doing it Wrong。 (儘管應該注意的是,現在Underscore 有一個fp 選項可以幫助解決Brian 在將Underscore 與函數式編程庫(例如lodash-fp 或Ramda)一起使用時討論的函數式編程問題。)無論如何,我們真正想要做的是首先傳入所有配置數據,然後最後傳入要操作的值。因此,將我們的組合函數定義為讀取其參數並從右到左應用它們最合乎邏輯。因此,我們可以創建一個看起來像這樣的基本組合函數:

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
console.log(addOne(timesTwo(3))); //7
console.log(timesTwo(addOne(3))); //8

使用這個非常簡單的組合函數,我們可以更簡單地構建我們之前的兩個複雜函數,並看到結果相同:

// ...来自上面的先前函数定义
function addOneTimesTwo(x) {
  var holder = x;
  holder = addOne(holder);
  holder = timesTwo(holder);
  return holder;
}
console.log(addOneTimesTwo(3)); //8
console.log(addOneTimesTwo(4)); //10

雖然這個簡單的組合函數有效,但它並沒有考慮許多限制其靈活性和適用性的問題。例如,我們可能想要組合兩個以上的函數。此外,我們在此過程中會丟失這些信息。我們可以解決這些問題,但為了掌握組合的工作原理,這不是必需的。與其自己編寫,不如從現有的函數式庫(例如 Ramda)繼承更強大的組合,默認情況下,它確實考慮了參數從右到左的順序。

類型是你的責任

重要的是要記住,程序員有責任知道每個被組合函數的返回類型,以便下一個函數可以正確處理它。與執行嚴格類型檢查的純函數式編程語言不同,JavaScript 不會阻止你嘗試組合返回不合適類型值的函數。你不僅限於傳遞數字,甚至不限於從一個函數到下一個函數保持相同的變量類型。但是你負責確保你正在組合的函數已準備好處理前一個函數返回的任何值。

考慮你的受眾

始終記住,其他人將來可能需要使用或修改你的代碼。在傳統的 JavaScript 代碼中使用組合對於不熟悉函數式編程範式的人來說可能會顯得複雜。目標是更簡潔、更易於閱讀和維護的代碼。但是,隨著 ES2015 語法的出現,甚至可以使用箭頭函數將簡單的組合函數作為單行調用來創建,而無需特殊的組合方法:

function addOne(x) {
  return x + 1;
}
function timesTwo(x) {
  return x * 2;
}
console.log(addOne(timesTwo(3))); //7
console.log(timesTwo(addOne(3))); //8

今天就開始組合吧

與所有函數式編程技術一樣,重要的是要記住你的組合函數應該是純函數。簡而言之,這意味著每次將特定值傳遞給函數時,函數都應返回相同的結果,並且函數不應產生改變自身外部值的副作用。當您有一組想要應用於數據的相關功能,並且您可以將該功能的組件分解為可重用且易於組合的函數時,組合嵌套非常方便。與所有函數式編程技術一樣,我建議謹慎地將組合添加到你的現有代碼中以熟悉它。如果你做對了,結果將是更簡潔、更乾燥、更易讀的代碼。難道這不是我們都想要的嗎?

(以下為FAQ,已根據原文進行調整和精簡,並避免重複信息)

關於函數組合和可維護代碼的常見問題

  • 什麼是編程中的函數組合? 函數組合是將簡單函數組合成更複雜函數的概念。你可以像搭積木一樣,用這些小型可重用的函數創建複雜、強大的功能。這有助於使代碼更易讀、更易維護和更具可擴展性。

  • 函數組合如何促進可維護的代碼? 函數組合通過鼓勵使用小型、可重用的函數來促進可維護性。這些函數更容易理解、測試和調試。當這些小型函數組合在一起以創建更複雜的功能時,更容易查明和修復可能出現的任何問題。這種模塊化方法還可以更容易地更新或修改代碼的某些部分,而不會影響整個系統。

  • 編寫可維護代碼的最佳實踐是什麼? 編寫可維護的代碼涉及多項最佳實踐,包括:保持函數小巧且專注於單一任務;使用有意義的變量和函數名稱;對代碼進行註釋以解釋代碼邏輯背後的“原因”;遵循一致的編碼風格和結構。

  • 函數組合與函數式編程有何關係? 函數組合是函數式編程中的一個基本概念。函數式編程是一種將計算視為數學函數的求值並避免更改狀態和可變數據的範例。在這種範例中,函數組合在從更簡單的函數構建更複雜的函數中起著至關重要的作用,從而提高了代碼的可重用性和可維護性。

  • 實現函數組合的挑戰是什麼? 函數組合雖然有很多好處,但也可能帶來挑戰。一個挑戰是,如果管理不當,它可能會導致難以閱讀的代碼,尤其是在組合多個函數時。在組合函數鏈中處理錯誤和異常也可能很困難。但是,可以通過良好的編碼實踐和正確使用函數組合來減輕這些挑戰。

  • 函數組合如何改進代碼測試? 函數組合可以使代碼測試更輕鬆、更高效。由於組合函數是由較小、獨立的函數組成的,因此你可以單獨測試每個小型函數。這使得更容易隔離和修復錯誤。它還促進了單元測試的實踐,其中軟件的每個部分都單獨進行測試以確保其正常工作。

以上是功能組成:可維護代碼的構建塊的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
在JavaScript中替換字符串字符在JavaScript中替換字符串字符Mar 11, 2025 am 12:07 AM

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

構建您自己的Ajax Web應用程序構建您自己的Ajax Web應用程序Mar 09, 2025 am 12:11 AM

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

10個JQuery Fun and Games插件10個JQuery Fun and Games插件Mar 08, 2025 am 12:42 AM

10款趣味橫生的jQuery遊戲插件,讓您的網站更具吸引力,提升用戶粘性!雖然Flash仍然是開發休閒網頁遊戲的最佳軟件,但jQuery也能創造出令人驚喜的效果,雖然無法與純動作Flash遊戲媲美,但在某些情況下,您也能在瀏覽器中獲得意想不到的樂趣。 jQuery井字棋遊戲 遊戲編程的“Hello world”,現在有了jQuery版本。 源碼 jQuery瘋狂填詞遊戲 這是一個填空遊戲,由於不知道單詞的上下文,可能會產生一些古怪的結果。 源碼 jQuery掃雷遊戲

如何創建和發布自己的JavaScript庫?如何創建和發布自己的JavaScript庫?Mar 18, 2025 pm 03:12 PM

文章討論了創建,發布和維護JavaScript庫,專注於計劃,開發,測試,文檔和促銷策略。

jQuery視差教程 - 動畫標題背景jQuery視差教程 - 動畫標題背景Mar 08, 2025 am 12:39 AM

本教程演示瞭如何使用jQuery創建迷人的視差背景效果。 我們將構建一個帶有分層圖像的標題橫幅,從而創造出令人驚嘆的視覺深度。 更新的插件可與JQuery 1.6.4及更高版本一起使用。 下載

如何在瀏覽器中優化JavaScript代碼以進行性能?如何在瀏覽器中優化JavaScript代碼以進行性能?Mar 18, 2025 pm 03:14 PM

本文討論了在瀏覽器中優化JavaScript性能的策略,重點是減少執行時間並最大程度地減少對頁面負載速度的影響。

Matter.js入門:簡介Matter.js入門:簡介Mar 08, 2025 am 12:53 AM

Matter.js是一個用JavaScript編寫的2D剛體物理引擎。此庫可以幫助您輕鬆地在瀏覽器中模擬2D物理。它提供了許多功能,例如創建剛體並為其分配質量、面積或密度等物理屬性的能力。您還可以模擬不同類型的碰撞和力,例如重力摩擦力。 Matter.js支持所有主流瀏覽器。此外,它也適用於移動設備,因為它可以檢測觸摸並具有響應能力。所有這些功能都使其值得您投入時間學習如何使用該引擎,因為這樣您就可以輕鬆創建基於物理的2D遊戲或模擬。在本教程中,我將介紹此庫的基礎知識,包括其安裝和用法,並提供一

使用jQuery和Ajax自動刷新DIV內容使用jQuery和Ajax自動刷新DIV內容Mar 08, 2025 am 12:58 AM

本文演示瞭如何使用jQuery和ajax自動每5秒自動刷新DIV的內容。 該示例從RSS提要中獲取並顯示了最新的博客文章以及最後的刷新時間戳。 加載圖像是選擇

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尊渡假赌尊渡假赌尊渡假赌

熱工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具