JS中函數(shù)科里化的背景與應(yīng)用實(shí)例教程
背景
柯里化(Currying)是一種關(guān)于函數(shù)的高階技術(shù)。它不僅被用于 JavaScript,還被用于其他編程語(yǔ)言。函數(shù)柯里化又叫部分求值,維基百科中對(duì)柯里化 (Currying) 的定義為:
在數(shù)學(xué)和計(jì)算機(jī)科學(xué)中,柯里化是一種將使用多個(gè)參數(shù)的函數(shù)轉(zhuǎn)換成一系列使用一個(gè)參數(shù)的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。
用大白話來說就是只傳遞給函數(shù)一部分參數(shù)來調(diào)用它,讓它返回一個(gè)新函數(shù)去處理剩下的參數(shù)。使用一個(gè)簡(jiǎn)單的例子來介紹下,最常用的就是 add 函數(shù)了。
// add method const add = (...args) => args.reduce((a, b) => a + b); // 傳入多個(gè)參數(shù),執(zhí)行 add 函數(shù) add(1, 2) // 返回 3 // 假設(shè)我們實(shí)現(xiàn)了一個(gè) currying 函數(shù),支持一次傳入一個(gè)參數(shù) let sum = currying(add); let addCurryOne = sum(1); addCurryOne(2) // 返回 3 addCurryOne(3) // 返回 4
使用場(chǎng)景
柯里化是一種函數(shù)的轉(zhuǎn)換,它是指將一個(gè)函數(shù)從可調(diào)用的 f(a, b, c) 轉(zhuǎn)換為可調(diào)用的 f(a)(b)(c)。柯里化不會(huì)調(diào)用函數(shù)。它只是對(duì)函數(shù)進(jìn)行轉(zhuǎn)換。 在平常工作中主要使用場(chǎng)景如下:
1、延遲計(jì)算(部分求和、bind 函數(shù))
2、動(dòng)態(tài)創(chuàng)建函數(shù)(添加監(jiān)聽 addEvent、惰性函數(shù))
3、參數(shù)復(fù)用(Function.prototype.call.bind(Object.prototype.toString))
JS中的函數(shù)科里化
可以對(duì)比下haskell這種天然的函數(shù)式語(yǔ)言,js里的珂里化實(shí)在是殘缺不全...但是利用珂里化這種參數(shù)對(duì)應(yīng)函數(shù)的思想,結(jié)合js的閉包特性,來實(shí)現(xiàn)良好的封裝。 舉個(gè)例子:js中最常見的dom的插入和刪除。 普通寫法:變量都在外部,不能確保每個(gè)remove操作都“正確”的
var append = function (parent, child) { parent.appendChild(child); } var remove = function (dom) { dom.remove(); } //插入 remove(child); //刪除 append(parent, child);
文藝寫法:確保了每個(gè)刪除操作都會(huì)刪除插入的節(jié)點(diǎn)。
var append = function (parent, child) { parent.appendChild(child); return function () { child.remove(); } } //或者是這種,point free風(fēng)格 var append2 = function (parent, child) { parent.appendChild(child); return child.remove.bind(child); } //插入一個(gè)節(jié)點(diǎn),同時(shí)返回所插入的節(jié)點(diǎn)的刪除操作。 remove(); //刪除。 var remove = append(parent, child);
總結(jié)一下就是說,這種以函作為主體,確保了函數(shù)之間不會(huì)相互干擾,尤其是在復(fù)雜的前端工程下,每一處的代碼越“安全”,越獨(dú)立,越能更好的拓展功能和排查問題。
經(jīng)典面試題:add(1)(2)(3)
function add(seed) { function retVal(later) { return add(seed + later); } retVal.toString = function () { return seed; }; return retVal; } console.log(add(1)(2)(3).toString()); // 6
add函數(shù)返回閉包retVal,在retVal中又繼續(xù)調(diào)用add,最終我們可以寫成add(1)(2)(3)(...)這樣柯里化的形式。 每調(diào)用一次add函數(shù),都會(huì)返回retValue函數(shù);調(diào)用retValue函數(shù)會(huì)調(diào)用add函數(shù),然后還是返回retValue函數(shù),所以調(diào)用add的結(jié)果一定是返回一個(gè)retValue函數(shù)。add函數(shù)的存在意義只是為了提供閉包,這個(gè)類似的遞歸調(diào)用每次調(diào)用add都會(huì)生成一個(gè)新的閉包。
總結(jié)
優(yōu)點(diǎn):
- 參數(shù)復(fù)用
- 提前返回
- 延遲計(jì)算/運(yùn)行
缺點(diǎn):
- 函數(shù)柯里化可以用來構(gòu)建復(fù)雜的算法 和 功能, 但是濫用也會(huì)帶來額外的開銷。從上面實(shí)現(xiàn)部分的代碼中,可以看到,使用柯里化函數(shù),離不開閉包, arguments, 遞歸。
- 閉包,函數(shù)中的變量都保存在內(nèi)存中,內(nèi)存消耗大,有可能導(dǎo)致內(nèi)存泄漏。
- 遞歸,效率非常
- arguments, 變量存取慢,訪問性很差
我個(gè)人覺得柯里化并非是必須的,而且不熟悉的同學(xué)閱讀起來可能會(huì)遇到麻煩,但是它能幫助我們理解JS中的函數(shù)式編程,更重要的是,我們以后在閱讀類似的代碼時(shí),不會(huì)感到陌生。
并非“柯里化”對(duì)函數(shù)式編程有意義。而是,函數(shù)式編程在把函數(shù)當(dāng)作一等公民的同時(shí),就不可避免的會(huì)產(chǎn)生“柯里化”這種用法。所以它并不是因?yàn)?ldquo;有什么意義”才出現(xiàn)的。
到此這篇關(guān)于JS中函數(shù)科里化的背景與應(yīng)用的文章就介紹到這了,更多相關(guān)JS函數(shù)科里化應(yīng)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript對(duì)象_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了JavaScript對(duì)象的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06實(shí)例分析JS中的相等性判斷===、 ==和Object.is()
這篇文章主要給大家介紹了關(guān)于JS中相等性判斷===、 ==和Object.is()的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用JS具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11讓ie6也支持websocket采用flash封裝實(shí)現(xiàn)
ie9都不支持websocket,何況ie6,往往這些不可思議的事情卻意想不到的發(fā)生了;websocket能開發(fā)那么酷的功能,怎么能讓ie攔住我們的腳步,用falsh封裝吧,感興趣的你可不要錯(cuò)過了哈2013-02-02JS跳出循環(huán)的方法區(qū)別對(duì)比分析(break,continue,return)
面向?qū)ο缶幊陶Z(yǔ)法中我們會(huì)碰到break ,continue, return這三個(gè)常用的關(guān)鍵字,那么關(guān)于這三個(gè)關(guān)鍵字的使用具體的操作是什么呢?接下來通過本文給大家講解JS跳出循環(huán)的方法區(qū)別對(duì)比分析(break,continue,return),感興趣的朋友一起看看吧2023-02-02簡(jiǎn)單實(shí)現(xiàn)js選項(xiàng)卡切換效果
這篇文章主要為大家介紹了簡(jiǎn)單實(shí)現(xiàn)js選項(xiàng)卡切換效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-02-02科訊商業(yè)版中用到的ajax空間與分頁(yè)函數(shù)
科訊商業(yè)版中用到的ajax空間與分頁(yè)函數(shù)...2007-09-09淺談使用splice函數(shù)對(duì)數(shù)組中的元素進(jìn)行刪除時(shí)的注意事項(xiàng)
下面小編就為大家?guī)硪黄獪\談使用splice函數(shù)對(duì)數(shù)組中的元素進(jìn)行刪除時(shí)的注意事項(xiàng)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-12-12