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