JS中函數(shù)科里化的背景與應(yīng)用實例教程
背景
柯里化(Currying)是一種關(guān)于函數(shù)的高階技術(shù)。它不僅被用于 JavaScript,還被用于其他編程語言。函數(shù)柯里化又叫部分求值,維基百科中對柯里化 (Currying) 的定義為:
在數(shù)學(xué)和計算機科學(xué)中,柯里化是一種將使用多個參數(shù)的函數(shù)轉(zhuǎn)換成一系列使用一個參數(shù)的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。
用大白話來說就是只傳遞給函數(shù)一部分參數(shù)來調(diào)用它,讓它返回一個新函數(shù)去處理剩下的參數(shù)。使用一個簡單的例子來介紹下,最常用的就是 add 函數(shù)了。
// add method const add = (...args) => args.reduce((a, b) => a + b); // 傳入多個參數(shù),執(zhí)行 add 函數(shù) add(1, 2) // 返回 3 // 假設(shè)我們實現(xiàn)了一個 currying 函數(shù),支持一次傳入一個參數(shù) let sum = currying(add); let addCurryOne = sum(1); addCurryOne(2) // 返回 3 addCurryOne(3) // 返回 4
使用場景
柯里化是一種函數(shù)的轉(zhuǎn)換,它是指將一個函數(shù)從可調(diào)用的 f(a, b, c) 轉(zhuǎn)換為可調(diào)用的 f(a)(b)(c)??吕锘粫{(diào)用函數(shù)。它只是對函數(shù)進(jìn)行轉(zhuǎn)換。 在平常工作中主要使用場景如下:
1、延遲計算(部分求和、bind 函數(shù))
2、動態(tài)創(chuàng)建函數(shù)(添加監(jiān)聽 addEvent、惰性函數(shù))
3、參數(shù)復(fù)用(Function.prototype.call.bind(Object.prototype.toString))
JS中的函數(shù)科里化
可以對比下haskell這種天然的函數(shù)式語言,js里的珂里化實在是殘缺不全...但是利用珂里化這種參數(shù)對應(yīng)函數(shù)的思想,結(jié)合js的閉包特性,來實現(xiàn)良好的封裝。 舉個例子:js中最常見的dom的插入和刪除。 普通寫法:變量都在外部,不能確保每個remove操作都“正確”的
var append = function (parent, child) {
parent.appendChild(child);
}
var remove = function (dom) {
dom.remove();
}
//插入 remove(child); //刪除
append(parent, child); 文藝寫法:確保了每個刪除操作都會刪除插入的節(jié)點。
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);
}
//插入一個節(jié)點,同時返回所插入的節(jié)點的刪除操作。 remove(); //刪除。
var remove = append(parent, child);總結(jié)一下就是說,這種以函作為主體,確保了函數(shù)之間不會相互干擾,尤其是在復(fù)雜的前端工程下,每一處的代碼越“安全”,越獨立,越能更好的拓展功能和排查問題。
經(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()); // 6add函數(shù)返回閉包retVal,在retVal中又繼續(xù)調(diào)用add,最終我們可以寫成add(1)(2)(3)(...)這樣柯里化的形式。 每調(diào)用一次add函數(shù),都會返回retValue函數(shù);調(diào)用retValue函數(shù)會調(diào)用add函數(shù),然后還是返回retValue函數(shù),所以調(diào)用add的結(jié)果一定是返回一個retValue函數(shù)。add函數(shù)的存在意義只是為了提供閉包,這個類似的遞歸調(diào)用每次調(diào)用add都會生成一個新的閉包。
總結(jié)
優(yōu)點:
- 參數(shù)復(fù)用
- 提前返回
- 延遲計算/運行
缺點:
- 函數(shù)柯里化可以用來構(gòu)建復(fù)雜的算法 和 功能, 但是濫用也會帶來額外的開銷。從上面實現(xiàn)部分的代碼中,可以看到,使用柯里化函數(shù),離不開閉包, arguments, 遞歸。
- 閉包,函數(shù)中的變量都保存在內(nèi)存中,內(nèi)存消耗大,有可能導(dǎo)致內(nèi)存泄漏。
- 遞歸,效率非常
- arguments, 變量存取慢,訪問性很差
我個人覺得柯里化并非是必須的,而且不熟悉的同學(xué)閱讀起來可能會遇到麻煩,但是它能幫助我們理解JS中的函數(shù)式編程,更重要的是,我們以后在閱讀類似的代碼時,不會感到陌生。
并非“柯里化”對函數(shù)式編程有意義。而是,函數(shù)式編程在把函數(shù)當(dāng)作一等公民的同時,就不可避免的會產(chǎn)生“柯里化”這種用法。所以它并不是因為“有什么意義”才出現(xiàn)的。
到此這篇關(guān)于JS中函數(shù)科里化的背景與應(yīng)用的文章就介紹到這了,更多相關(guān)JS函數(shù)科里化應(yīng)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript常用數(shù)學(xué)函數(shù)用法示例
這篇文章主要介紹了JavaScript常用數(shù)學(xué)函數(shù)用法,結(jié)合實例形式分析了JavaScript常見的對數(shù)、平方、絕對值、正弦、四舍五入等相關(guān)數(shù)學(xué)函數(shù)使用技巧,需要的朋友可以參考下2018-05-05
bootstrap學(xué)習(xí)筆記之初識bootstrap
Bootstrap是一款目前非常流行的前端框架,簡單的說,就是html,css,javascript的工具集。本文給大家介紹bootstrap學(xué)習(xí)筆記之初識bootstrap,感興趣的朋友一起學(xué)習(xí)吧2016-06-06
javascript中的相等操作符(==與===區(qū)別)
這篇文章主要介紹了javascript中的相等操作符(==與===區(qū)別),需要的朋友可以參考下2019-12-12

