摘要:而柯里化是一個屬于函數(shù)式編程的一個常見的技巧。簡單來說,函數(shù)柯里化就是對高階函數(shù)的降階處理。讓你意外的是,這就是柯里化的基本思想,簡單地讓人猝不及防。
函數(shù)式編程是一種被部分JavaScript程序員推崇的編程風(fēng)格,更別說 Haskell 和 Scala 這種以函數(shù)式為教義的語言。原因是因為其能用較短的代碼實現(xiàn)功能,如果掌握得當(dāng),能達(dá)到代碼文檔化(代碼本身具有很高可讀性甚至可以代替文檔)的效果,當(dāng)然,泛濫使用也會使代碼可讀性變差。
而柯里化(Currying)是一個屬于函數(shù)式編程的一個常見的技巧。簡單來說,函數(shù)柯里化就是對高階函數(shù)的降階處理。
我們看下面這個函數(shù):
function loc (a,b,c){ console.log(a+"-"+b+"-"+c); } loc("浙江","杭州","西湖區(qū)");//>>>浙江-杭州-西湖區(qū)
這是一個接收三個地名字符串的函數(shù),功能是將三個地名字符串拼接到一起成為一個詳細(xì)的地址。
我們試試只傳入兩個參數(shù):
loc("浙江","杭州");//>>>浙江-杭州-undefined
毫無疑義地,這個函數(shù)還是會正常執(zhí)行,只是原本屬于“區(qū)”的位置由于沒有接收到參數(shù)而成了undefined。
其實這種情況很多,比如我們還要生成浙江-杭州-余杭區(qū),浙江-杭州-拱墅區(qū)這樣的地名,但是我們沒必要每次都重新把浙江-杭州重新拼接一遍,所以你是不是會想,能不能只通過一個函數(shù),把已經(jīng)拼接過的字符串緩存起來,只去拼接新的字符串呢?我們或許可以把之前的函數(shù)改一下:
function loc (a) { return function(b){ return function(c){ console.log(a+"-"+b+"-"+c); } } }
好奇怪!這個loc函數(shù)只接收一個參數(shù),而返回一個新的函數(shù),這個函數(shù)也只接受一個參數(shù),里面同樣返回一個函數(shù),最后一個函數(shù)才返回三個參數(shù)拼接的字符串。
看起來是一個嵌套關(guān)系,好吧,讓我們看看它是否能實現(xiàn)剛剛的想法:
var Zhejiang = loc("浙江"); var Hangzhou = Zhejiang("杭州"); var Xihu = Hangzhou("西湖區(qū)"); //浙江-杭州-西湖區(qū) var Yuhang = Hangzhou("余杭區(qū)"); //浙江-杭州-余杭區(qū) var Lucheng = Zhejiang("溫州")("鹿城區(qū)"); //浙江-溫州-鹿城區(qū)
看,通過這樣的形式,我們輕松實現(xiàn)定制化函數(shù)啦!loc("杭州")不會急著把地名都拼接好,而是把杭州先存到閉包中,在需要拼接的時候才用到它。
讓你意外的是,這就是柯里化的基本思想,簡單地讓人猝不及防。
不,這不是你想要的結(jié)果,至少你已經(jīng)考慮到一種恐怖的情況:如果參數(shù)有許多——比如100個,是不是要寫一個嵌套一百次的函數(shù)?
好在,我們可以寫一個通用函數(shù)來優(yōu)雅地創(chuàng)建柯里化函數(shù):
function curry(fn) { var outerArgs = Array.prototype.slice.call(arguments, 1); return function() { var innerArgs = Array.prototype.slice.call(arguments), finalArgs = outerArgs.concat(innerArgs); return fn.apply(null, finalArgs); }; }
有了這個基本函數(shù)之后,我們可以柯里化其他普通函數(shù):
//一個普通函數(shù) function loc(a,b,c){ console.log(a+"-"+b+"-"+c); } var workIn = curry(loc,"浙江","杭州","余杭區(qū)"); workIn();// >>> 浙江-杭州-余杭區(qū)
當(dāng)然也可以這樣定制:
var zj = curry(loc,"浙江"); var city = curry(zj,"杭州"); city("余杭區(qū)"); //>>> 浙江-杭州-余杭區(qū) city("上城區(qū)"); //>>> 浙江-杭州-上城區(qū) zj("溫州","鹿城區(qū)");//>>> 浙江-溫州-鹿城區(qū)
簡直優(yōu)雅。
以下我們來簡單分析以下這個通用函數(shù):
function curry(fn) { var outerArgs = Array.prototype.slice.call(arguments, 1); return function() { var innerArgs = Array.prototype.slice.call(arguments), finalArgs = outerArgs.concat(innerArgs); return fn.apply(null, finalArgs); }; }
我們看這個curry函數(shù),顯示接受一個參數(shù),那就是需要被柯里化的函數(shù)。同時,因為JS神奇的函數(shù)傳參,我們可以在curry繼續(xù)放更多的參數(shù),這些參數(shù)在函數(shù)體內(nèi)部將以參數(shù)列表的形式存在,你可以通過arguments引用這個參數(shù)列表。注意,arguments引用的是一個參數(shù)列表而不是數(shù)組(雖然很像),所以數(shù)組的很多方法它都沒有。當(dāng)然,這個難不倒我們,還記得我上一篇文章里提到的apply()黑科技嗎?傳送門:《快速理解JavaScript中apply()和call()的用法和用途》
outerArgs就是獲取除了第一個參數(shù)之外的參數(shù)列表。
而在返回的函數(shù)里,innerArgs獲取的是調(diào)用這個返回函數(shù)時傳入的所有參數(shù),比如之前city("上城區(qū)")里面的"上城區(qū)"。
而finalArgs則是拼接這兩個數(shù)組(注意此時兩個參數(shù)列表都已經(jīng)是正宗的數(shù)組,所以才可以使用concat方法)。
最后,使用apply,把所有參數(shù)組成的列表傳入到原來的函數(shù),其實質(zhì)就是在調(diào)用原始的函數(shù),因為此時的參數(shù)都已齊全。
結(jié)尾福利:
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/78887.html
摘要:函數(shù)式編程,一看這個詞,簡直就是學(xué)院派的典范。所以這期周刊,我們就重點引入的函數(shù)式編程,淺入淺出,一窺函數(shù)式編程的思想,可能讓你對編程語言的理解更加融會貫通一些。但從根本上來說,函數(shù)式編程就是關(guān)于如使用通用的可復(fù)用函數(shù)進(jìn)行組合編程。 showImg(https://segmentfault.com/img/bVGQuc); 函數(shù)式編程(Functional Programming),一...
摘要:以案例中的漏洞為例,安騎士的修復(fù)建議功能通過漏洞真實影響分析,能快速計算出漏洞真實受到影響較大的機(jī)器,在非常短的時間內(nèi)給出企業(yè)修復(fù)排序的有效建議。 摘要: 關(guān)注網(wǎng)絡(luò)安全的企業(yè)大都很熟悉這樣的場景:幾乎每天都會通過安全媒體和網(wǎng)絡(luò)安全廠商接收到非常多的漏洞信息,并且會被建議盡快修復(fù)。盡管越來越多的企業(yè)對網(wǎng)絡(luò)安全的投入逐年增加,但第一時間修復(fù)所有漏洞,仍然是一件非常有挑戰(zhàn)的事。 關(guān)注網(wǎng)絡(luò)安全...
摘要:原文鏈接和都支持函數(shù)的柯里化函數(shù)的柯里化還與的函數(shù)編程有很大的聯(lián)系如果你感興趣的話可以在這些方面多下功夫了解相信收獲一定很多看本篇文章需要知道的一些知識點函數(shù)部分的閉包高階函數(shù)不完全函數(shù)文章后面有對這些知識的簡單解釋大家可以看看什么是柯里化 原文鏈接 Haskell和scala都支持函數(shù)的柯里化,JavaScript函數(shù)的柯里化還與JavaScript的函數(shù)編程有很大的聯(lián)系,如果你感興...
摘要:作為函數(shù)式編程語言,帶來了很多語言上的有趣特性,比如柯里化和反柯里化。在一些函數(shù)式編程語言中,會定義一個特殊的占位變量。個人理解不知道對不對延遲執(zhí)行柯里化的另一個應(yīng)用場景是延遲執(zhí)行。不斷的柯里化,累積傳入的參數(shù),最后執(zhí)行。作為函數(shù)式編程語言,JS帶來了很多語言上的有趣特性,比如柯里化和反柯里化。 這里可以對照另外一篇介紹 JS 反柯里化 的文章一起看~ 1. 簡介 柯里化(Currying)...
摘要:作為函數(shù)式編程語言,帶來了很多語言上的有趣特性,比如柯里化和反柯里化。而反柯里化,從字面講,意義和用法跟函數(shù)柯里化相比正好相反,擴(kuò)大適用范圍,創(chuàng)建一個應(yīng)用范圍更廣的函數(shù)。作為函數(shù)式編程語言,JS帶來了很多語言上的有趣特性,比如柯里化和反柯里化。 可以對照另外一篇介紹 JS 柯里化 的文章一起看~ 1. 簡介 柯里化,是固定部分參數(shù),返回一個接受剩余參數(shù)的函數(shù),也稱為部分計算函數(shù),目的是為了縮...
閱讀 3096·2021-11-24 10:47
閱讀 3855·2021-11-02 14:43
閱讀 2245·2021-09-26 10:15
閱讀 2304·2021-09-08 09:35
閱讀 581·2019-08-30 12:45
閱讀 2789·2019-08-29 17:04
閱讀 3223·2019-08-26 14:05
閱讀 1272·2019-08-26 12:10