摘要:我們終于寫完了這個神奇的函數,它真的很強大,配合,那真是一個字,爽。
最近在學習javascript函數式編程,對其中大名鼎鼎的curry十分感興趣,curry函數可以接受一個函數,我們暫且稱之為原始函數,返回的也是一個函數,柯里化函數,這個返回的柯里化函數功能十分強大,他在執行的過程中,不斷的返回一個貯存了傳入參數的函數,直到觸發了原始函數執行的條件。這么說比較概括,那么就舉個例子來說明一下:
原始函數:
var add = (x, y) => x + y
柯里化函數:
var curryAdd = curry(add)
這個add需要兩個參數,但是我們的curryAdd執行可以傳入更少的參數,當傳入的參數少于add需要的參數的時候,add函數并不會執行,curryAdd就會將這個參數記下來,并且返回另外一個函數,這個函數可以繼續執行傳入參數,我們會有一個變量專門記錄傳入參數的情況,如果傳入參數的總數等于add需要參數的總數,我們就激活了原始參數執行,就會返回我們想要的結果。
// 此時只傳入了一個參數 根據判斷返回的是一個函數 var add2 = curryAdd(2) // add2 = function(...) {}
// 此時累計傳入了兩個參數 等于了add需要參數的總和 所以返回的是一個結果 // 相當于執行了add(2)(3) var result = add2(3) // result = 5
還是很不錯的是吧,好吧,我們的目的是為了寫出這個神奇curry函數,而且還要一行寫出來,不要著急,先分析一下怎么去寫,然后再一步步的優化。
那根據上面的描述,我們看一下curry函數需要什么,首先需要一個變量,用來存下來原始函數的參數個數,我們知道function有一個屬性為length,對就是它,我們用limit存下來
var curry = function(fn) { var limit = fn.length ... }
curry函數要返回一個函數, 這個函數是要執行的,那么問題就是,我們要判斷這個函數的執行是否激活了原始函數的執行,問題就出現在傳入的參數上面。返回函數還是結果?這的確是一個問題,
我們先寫返回結果的情況,當傳入的參數等于原始函數需要的參數時,我們執行原始函數fn
var curry = function(fn) { var limit = fn.length return function (...args) { if (args.length >= limit) { return fn.apply(null, args) } } }
否則呢 我們就要返回一個貯存了參數的函數,這里有兩點,一是參數的傳入歷史我們要記錄下來,二是這個返回的函數需要做些什么
var curry = function(fn) { var limit = fn.length return function (...args) { if (args.length >= limit) { return fn.apply(null, args) } else { return function(...args2) { } } } }
看出來了吧 我們只需要把返回函數執行的參數累加起來就達到了記錄參數傳入情況的目的,于是我們想到了concat 對 args.concat(args2), 依次類推,我們返回的函數要做的就是重復做上面的事情,也就是參數為args的函數要做的事情,所以他需要一個名字,不然我們沒法執行,我們叫它judgeCurry
所以正如我們所說的,要么返回一個函數,要么執行原始函數。
var curry = function(fn) { var limit = fn.length return function judgeCurry (...args) { if (args.length >= limit) { return fn.apply(null, args) } else { return function(...args2) { return judgeCurry.apply(null, args.concat(args2)) } } } }
我們終于寫完了這個神奇的curry函數,它真的很強大,配合compose,那真是一個字,爽。
我們的目的還是一行把上面那個函數寫出來,一行寫?怎么寫?對了,用ES6啊,于是一番折騰
var currySingle = fn => judgeCurry = (...args) => args.length >= fn.length ? fn.apply(null, args) : (...args2) => judgeCurry.apply(null, args.concat(args2))
好,我們看一下哪有問題,對了,就是我們為了不用limit參數,用了就得賦值,賦值就不能一行搞定了,就會變成這樣
var currySingle = fn => { var limit = fn.length var judgeCurry = null return judgeCurry = (...args) => args.length >= limit ? fn.apply(null, args) : (...args2) => judgeCurry.apply(null, args.concat(args2)) }
需要判斷參數的時候不斷的對fn.length求值,但是fn.length的值是確定的,我們不想每次都求值,但又不想用limit怎么辦,有什么辦法呢?你一定想到了,立即執行函數!!
var currySingle = fn => ((limit) => judgeCurry = (...args) => args.length >= limit ? fn.apply(null, args) : (...args2) => judgeCurry.apply(null, args.concat(args2)))(fn.length)
不得不感嘆javascript的神奇,終于,我們就一行將這個神奇的curry寫出來了。。。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81392.html
摘要:組合的概念是非常直觀的,并不是函數式編程獨有的,在我們生活中或者前端開發中處處可見。其實我們函數式編程里面的組合也是類似,函數組合就是一種將已被分解的簡單任務組織成復雜的整體過程。在函數式編程的世界中,有這樣一種很流行的編程風格。 JavaScript函數式編程,真香之認識函數式編程(一) 該系列文章不是針對前端新手,需要有一定的編程經驗,而且了解 JavaScript 里面作用域,閉...
摘要:譯者團隊排名不分先后阿希冬青蘿卜萌萌輕量級函數式編程第章融會貫通現在你已經掌握了所有需要掌握的關于輕量級函數式編程的內容。回頭想想我們用到的函數式編程原則。這兩個函數組合成一個映射函數通過,這就是融合見第章。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關于譯者:這是一個流淌著滬江血液的純粹工程:...
摘要:所以下面介紹一些函數式編程的知識和概念。函數式編程的一個明顯的好處就是這種聲明式的代碼,對于無副作用的純函數,我們完全可以不考慮函數內部是如何實現的,專注于編寫業務代碼。我會在下一篇文章中介紹函數式編程的更加高階一些的知識,例如等等概念。 一、引言 說到函數式編程,大家可能第一印象都是學院派的那些晦澀難懂的代碼,充滿了一大堆抽象的不知所云的符號,似乎只有大學里的計算機教授才會使用這些東...
摘要:原文鏈接和都支持函數的柯里化函數的柯里化還與的函數編程有很大的聯系如果你感興趣的話可以在這些方面多下功夫了解相信收獲一定很多看本篇文章需要知道的一些知識點函數部分的閉包高階函數不完全函數文章后面有對這些知識的簡單解釋大家可以看看什么是柯里化 原文鏈接 Haskell和scala都支持函數的柯里化,JavaScript函數的柯里化還與JavaScript的函數編程有很大的聯系,如果你感興...
摘要:高階函數函數式編程中,接受函數作為參數,或者返回一個函數作為結果的函數通常就被稱為高階函數。均屬于高階函數,高階函數并不神秘,我們日常編程也會用到。參考演算函數式編程指南入門康托爾哥德爾圖靈永恒的金色對角線原文函數與演算 緣起 造了一個輪子,根據GitHub項目地址,生成項目目錄樹,直觀的展現項目結構,以便于介紹項目。歡迎Star。 repository-tree 技術棧: ES6 ...
閱讀 1849·2021-09-29 09:35
閱讀 2711·2021-09-22 15:25
閱讀 1972·2021-08-23 09:43
閱讀 2049·2019-08-30 15:54
閱讀 3349·2019-08-30 15:53
閱讀 2387·2019-08-30 13:50
閱讀 2399·2019-08-30 11:24
閱讀 2269·2019-08-29 15:37