摘要:原文鏈接和都支持函數(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í)點(diǎn)
函數(shù)部分的call/apply/arguments
閉包
高階函數(shù)
不完全函數(shù)
文章后面有對(duì)這些知識(shí)的簡(jiǎn)單解釋,大家可以看看.
什么是柯里化?我們先來(lái)看看維基百科中是如何定義的:在計(jì)算機(jī)科學(xué)中,柯里化(英語(yǔ):Currying),又譯為卡瑞化或加里化,是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。
我們可以舉個(gè)簡(jiǎn)單的例子,如下函數(shù)add是一般的一個(gè)函數(shù),就是將傳進(jìn)來(lái)的參數(shù)a和b相加;函數(shù)curryingAdd就是對(duì)函數(shù)add進(jìn)行柯里化的函數(shù);
這樣一來(lái),原來(lái)我們需要直接傳進(jìn)去兩個(gè)參數(shù)來(lái)進(jìn)行運(yùn)算的函數(shù),現(xiàn)在需要分別傳入?yún)?shù)a和b,函數(shù)如下:
function add(a, b) { return a + b; } function curryingAdd(a) { return function(b) { return a + b; } } add(1, 2); // 3 curryingAdd(1)(2); // 3
看到這里你可能會(huì)想,這樣做有什么用?為什么要這樣做?這樣做能夠給我們的應(yīng)用帶來(lái)什么樣的好處?先別著急,我們接著往下看.
為什么要對(duì)函數(shù)進(jìn)行柯里化?可以使用一些小技巧(見(jiàn)下文)
提前綁定好函數(shù)里面的某些參數(shù),達(dá)到參數(shù)復(fù)用的效果,提高了適用性.
固定易變因素
延遲計(jì)算
總之,函數(shù)的柯里化能夠讓你重新組合你的應(yīng)用,把你的復(fù)雜功能拆分成一個(gè)一個(gè)的小部分,每一個(gè)小的部分都是簡(jiǎn)單的,便于理解的,而且是容易測(cè)試的;
如何對(duì)函數(shù)進(jìn)行柯里化?在這一部分里,我們由淺入深的一步步來(lái)告訴大家如何對(duì)一個(gè)多參數(shù)的函數(shù)進(jìn)行柯里化.其中用到的知識(shí)有閉包,高階函數(shù),不完全函數(shù)等等.
I 開(kāi)胃菜
假如我們要實(shí)現(xiàn)一個(gè)功能,就是輸出語(yǔ)句name喜歡song,其中name和song都是可變參數(shù);那么一般情況下我們會(huì)這樣寫(xiě):
function printInfo(name, song) { console.log(name + "喜歡的歌曲是: " + song); } printInfo("Tom", "七里香"); printInfo("Jerry", "雅俗共賞");
對(duì)上面的函數(shù)進(jìn)行柯里化之后,我們可以這樣寫(xiě):
function curryingPrintInfo(name) { return function(song) { console.log(name + "喜歡的歌曲是: " + song); } } var tomLike = curryingPrintInfo("Tom"); tomLike("七里香"); var jerryLike = curryingPrintInfo("Jerry"); jerryLike("雅俗共賞");
II 小雞燉蘑菇
上面我們雖然對(duì)對(duì)函數(shù)printInfo進(jìn)行了柯里化,但是我們可不想在需要柯里化的時(shí)候,都像上面那樣不斷地進(jìn)行函數(shù)的嵌套,那簡(jiǎn)直是噩夢(mèng);
所以我們要?jiǎng)?chuàng)造一些幫助其它函數(shù)進(jìn)行柯里化的函數(shù),我們暫且叫它為curryingHelper吧,一個(gè)簡(jiǎn)單的curryingHelper函數(shù)如下所示:
function curryingHelper(fn) { var _args = Array.prototype.slice.call(arguments, 1); return function() { var _newArgs = Array.prototype.slice.call(arguments); var _totalArgs = _args.concat(_newArgs); return fn.apply(this, _totalArgs); } }
這里解釋一點(diǎn)東西,首先函數(shù)的arguments表示的是傳遞到函數(shù)中的參數(shù)對(duì)象,它不是一個(gè)數(shù)組,它是一個(gè)類(lèi)數(shù)組對(duì)象;
所以我們可以使用函數(shù)的Array.prototype.slice方法,然后使用.call方法來(lái)獲取arguments里面的內(nèi)容.
我們使用fn.apply(this, _totalArgs)來(lái)給函數(shù)fn傳遞正確的參數(shù).
接下來(lái)我們來(lái)寫(xiě)一個(gè)簡(jiǎn)單的函數(shù)驗(yàn)證上面的輔助柯里化函數(shù)的正確性, 代碼部分如下:
function showMsg(name, age, fruit) { console.log("My name is " + name + ", I"m " + age + " years old, " + " and I like eat " + fruit); } var curryingShowMsg1 = curryingHelper(showMsg, "dreamapple"); curryingShowMsg1(22, "apple"); // My name is dreamapple, I"m 22 years old, and I like eat apple var curryingShowMsg2 = curryingHelper(showMsg, "dreamapple", 20); curryingShowMsg2("watermelon"); // My name is dreamapple, I"m 20 years old, and I like eat watermelon
上面的結(jié)果表示,我們的這個(gè)柯里化的函數(shù)是正確的.上面的curryingHelper就是一個(gè)高階函數(shù),關(guān)于高階函數(shù)的解釋可以參照下文.
III 牛肉火鍋
上面的柯里化幫助函數(shù)確實(shí)已經(jīng)能夠達(dá)到我們的一般性需求了,但是它還不夠好,我們希望那些經(jīng)過(guò)柯里化后的函數(shù)可以每次只傳遞進(jìn)去一個(gè)參數(shù),
然后可以進(jìn)行多次參數(shù)的傳遞,那么應(yīng)該怎么辦呢?我們可以再花費(fèi)一些腦筋,寫(xiě)出一個(gè)betterCurryingHelper函數(shù),實(shí)現(xiàn)我們上面說(shuō)的那些
功能.代碼如下:
function betterCurryingHelper(fn, len) { var length = len || fn.length; return function () { var allArgsFulfilled = (arguments.length >= length); // 如果參數(shù)全部滿(mǎn)足,就可以終止遞歸調(diào)用 if (allArgsFulfilled) { return fn.apply(this, arguments); } else { var argsNeedFulfilled = [fn].concat(Array.prototype.slice.call(arguments)); return betterCurryingHelper(curryingHelper.apply(this, argsNeedFulfilled), length - arguments.length); } }; }
其中curryingHelper就是上面II 小雞燉蘑菇中提及的那個(gè)函數(shù).需要注意的是fn.length表示的是這個(gè)函數(shù)的參數(shù)長(zhǎng)度.
接下來(lái)我們來(lái)檢驗(yàn)一下這個(gè)函數(shù)的正確性:
var betterShowMsg = betterCurryingHelper(showMsg); betterShowMsg("dreamapple", 22, "apple"); // My name is dreamapple, I"m 22 years old, and I like eat apple betterShowMsg("dreamapple", 22)("apple"); // My name is dreamapple, I"m 22 years old, and I like eat apple betterShowMsg("dreamapple")(22, "apple"); // My name is dreamapple, I"m 22 years old, and I like eat apple betterShowMsg("dreamapple")(22)("apple"); // My name is dreamapple, I"m 22 years old, and I like eat apple
其中showMsg就是II 小雞燉蘑菇部分提及的那個(gè)函數(shù).
我們可以看出來(lái),這個(gè)betterCurryingHelper確實(shí)實(shí)現(xiàn)了我們想要的那個(gè)功能.并且我們也可以像使用原來(lái)的那個(gè)函數(shù)一樣使用柯里化后的函數(shù).
IV 泡椒鳳爪
我們已經(jīng)能夠?qū)懗龊芎玫目吕锘o助函數(shù)了,但是這還不算是最刺激的,如果我們?cè)趥鬟f參數(shù)的時(shí)候可以不按照順來(lái)那一定很酷;當(dāng)然我們也可以寫(xiě)出這樣的函數(shù)來(lái),
這個(gè)crazyCurryingHelper函數(shù)如下所示:
var _ = {}; function crazyCurryingHelper(fn, length, args, holes) { length = length || fn.length; args = args || []; holes = holes || []; return function() { var _args = args.slice(), _holes = holes.slice(); // 存儲(chǔ)接收到的args和holes的長(zhǎng)度 var argLength = _args.length, holeLength = _holes.length; var allArgumentsSpecified = false; // 循環(huán) var arg = null, i = 0, aLength = arguments.length; for(; i < aLength; i++) { arg = arguments[i]; if(arg === _ && holeLength) { // 循環(huán)holes的位置 holeLength--; _holes.push(_holes.shift()); } else if (arg === _) { // 存儲(chǔ)hole就是_的位置 _holes.push(argLength + i); } else if (holeLength) { // 是否還有沒(méi)有填補(bǔ)的hole // 在參數(shù)列表指定hole的地方插入當(dāng)前參數(shù) holeLength--; _args.splice(_holes.shift(), 0, arg); } else { // 不需要填補(bǔ)hole,直接添加到參數(shù)列表里面 _args.push(arg); } } // 判斷是否所有的參數(shù)都已滿(mǎn)足 allArgumentsSpecified = (_args.length >= length); if(allArgumentsSpecified) { return fn.apply(this, _args); } // 遞歸的進(jìn)行柯里化 return crazyCurryingHelper.call(this, fn, length, _args, _holes); }; }
一些解釋,我們使用_來(lái)表示參數(shù)中的那些缺失的參數(shù),如果你使用了lodash的話,會(huì)有沖突的;那么你可以使用別的符號(hào)替代.
按照一貫的尿性,我們還是要驗(yàn)證一下這個(gè)crazyCurryingHelper是不是實(shí)現(xiàn)了我們所說(shuō)的哪些功能,代碼如下:
var crazyShowMsg = crazyCurryingHelper(showMsg); crazyShowMsg(_, 22)("dreamapple")("apple"); // My name is dreamapple, I"m 22 years old, and I like eat apple crazyShowMsg( _, 22, "apple")("dreamapple"); // My name is dreamapple, I"m 22 years old, and I like eat apple crazyShowMsg( _, 22, _)("dreamapple", _, "apple"); // My name is dreamapple, I"m 22 years old, and I like eat apple crazyShowMsg( "dreamapple", _, _)(22)("apple"); // My name is dreamapple, I"m 22 years old, and I like eat apple crazyShowMsg("dreamapple")(22)("apple"); // My name is dreamapple, I"m 22 years old, and I like eat apple
結(jié)果顯示,我們這個(gè)函數(shù)也實(shí)現(xiàn)了我們所說(shuō)的那些功能.
柯里化的一些應(yīng)用場(chǎng)景說(shuō)了那么多,其實(shí)這部分才是最重要的部分;學(xué)習(xí)某個(gè)知識(shí)要一定可以用得到,不然學(xué)習(xí)它干嘛.
關(guān)于函數(shù)柯里化的一些小技巧
給setTimeout傳遞地進(jìn)來(lái)的函數(shù)添加參數(shù)
一般情況下,我們?nèi)绻虢o一個(gè)setTimeout傳遞進(jìn)來(lái)的函數(shù)添加參數(shù)的話,一般會(huì)使用之種方法:
function hello(name) { console.log("Hello, " + name); } setTimeout(hello("dreamapple"), 3600); //立即執(zhí)行,不會(huì)在3.6s后執(zhí)行 setTimeout(function() { hello("dreamapple"); }, 3600); // 3.6s 后執(zhí)行
我們使用了一個(gè)新的匿名函數(shù)包裹我們要執(zhí)行的函數(shù),然后在函數(shù)體里面給那個(gè)函數(shù)傳遞參數(shù)值.
當(dāng)然,在ES5里面,我們也可以使用函數(shù)的bind方法,如下所示:
setTimeout(hello.bind(this, "dreamapple"), 3600); // 3.6s 之后執(zhí)行函數(shù)
這樣也是非常的方便快捷,并且可以綁定函數(shù)執(zhí)行的上下文.
我們本篇文章是討論函數(shù)的柯里化,當(dāng)然我們這里也可以使用函數(shù)的柯里化來(lái)達(dá)到這個(gè)效果:
setTimeout(curryingHelper(hello, "dreamapple"), 3600); // 其中curryingHelper是上面已經(jīng)提及過(guò)的
這樣也是可以的,是不是很酷.其實(shí)函數(shù)的bind方法也是使用函數(shù)的柯里化來(lái)完成的,詳情可以看這里Function.prototype.bind().
寫(xiě)出這樣一個(gè)函數(shù)multiply(1)(2)(3) == 6結(jié)果為true,multiply(1)(2)(3)(...)(n) == (1)*(2)*(3)*(...)*(n)結(jié)果為true
這個(gè)題目不知道大家碰到過(guò)沒(méi)有,不過(guò)通過(guò)函數(shù)的柯里化,也是有辦法解決的,看下面的代碼:
function multiply(x) { var y = function(x) { return multiply(x * y); }; y.toString = y.valueOf = function() { return x; }; return y; } console.log(multiply(1)(2)(3) == 6); // true console.log(multiply(1)(2)(3)(4)(5) == 120); // true
因?yàn)?b>multiply(1)(2)(3)的直接結(jié)果并不是6,而是一個(gè)函數(shù)對(duì)象{ [Number: 6] valueOf: [Function], toString: [Function] },我們
之后使用了==會(huì)將左邊這個(gè)函數(shù)對(duì)象轉(zhuǎn)換成為一個(gè)數(shù)字,所以就達(dá)到了我們想要的結(jié)果.還有關(guān)于為什么使用toString和valueOf方法
可以看看這里的解釋Number.prototype.valueOf(),Function.prototype.toString().
上面的那個(gè)函數(shù)不夠純粹,我們也可以實(shí)現(xiàn)一個(gè)更純粹的函數(shù),但是可以會(huì)不太符合題目的要求.
我們可以這樣做,先把函數(shù)的參數(shù)存儲(chǔ),然后再對(duì)這些參數(shù)做處理,一旦有了這個(gè)思路,我們就不難寫(xiě)出些面的代碼:
function add() { var args = Array.prototype.slice.call(arguments); var _that = this; return function() { var newArgs = Array.prototype.slice.call(arguments); var total = args.concat(newArgs); if(!arguments.length) { var result = 1; for(var i = 0; i < total.length; i++) { result *= total[i]; } return result; } else { return add.apply(_that, total); } } } add(1)(2)(3)(); // 6 add(1, 2, 3)(); // 6
當(dāng)我們的需要兼容IE9之前版本的IE瀏覽器的話,我們可能需要寫(xiě)出一些兼容的方案 ,比如事件監(jiān)聽(tīng);一般情況下我們應(yīng)該會(huì)這樣寫(xiě):
var addEvent = function (el, type, fn, capture) { if (window.addEventListener) { el.addEventListener(type, fn, capture); } else { el.attachEvent("on" + type, fn); } };
這也寫(xiě)也是可以的,但是性能上會(huì)差一點(diǎn),因?yàn)槿绻窃诘桶姹镜腎E瀏覽器上每一次都會(huì)運(yùn)行if()語(yǔ)句,產(chǎn)生了不必要的性能開(kāi)銷(xiāo).
我們也可以這樣寫(xiě):
var addEvent = (function () { if (window.addEventListener) { return function (el, type, fn, capture) { el.addEventListener(type, fn, capture); } } else { return function (el, type, fn) { var IEtype = "on" + type; el.attachEvent(IEtype, fn); } } })();
這樣就減少了不必要的開(kāi)支,整個(gè)函數(shù)運(yùn)行一次就可以了.
延遲計(jì)算
上面的那兩個(gè)函數(shù)multiply()和add()實(shí)際上就是延遲計(jì)算的例子.
提前綁定好函數(shù)里面的某些參數(shù),達(dá)到參數(shù)復(fù)用的效果,提高了適用性.
我們的I 開(kāi)胃菜部分的tomLike和jerryLike其實(shí)就是屬于這種的,綁定好函數(shù)里面的第一個(gè)參數(shù),然后后面根據(jù)情況分別使用不同的函數(shù).
固定易變因素
我們經(jīng)常使用的函數(shù)的bind方法就是一個(gè)固定易變因素的很好的例子.
關(guān)于柯里化的性能當(dāng)然,使用柯里化意味著有一些額外的開(kāi)銷(xiāo);這些開(kāi)銷(xiāo)一般涉及到這些方面,首先是關(guān)于函數(shù)參數(shù)的調(diào)用,操作arguments對(duì)象通常會(huì)比操作命名的參數(shù)要慢一點(diǎn);
還有,在一些老的版本的瀏覽器中arguments.length的實(shí)現(xiàn)是很慢的;直接調(diào)用函數(shù)fn要比使用fn.apply()或者fn.call()要快一點(diǎn);產(chǎn)生大量的嵌套
作用域還有閉包會(huì)帶來(lái)一些性能還有速度的降低.但是,大多數(shù)的web應(yīng)用的性能瓶頸時(shí)發(fā)生在操作DOM上的,所以上面的那些開(kāi)銷(xiāo)比起DOM操作的開(kāi)銷(xiāo)還是比較小的.
瑣碎的知識(shí)點(diǎn)
fn.length: 表示的是這個(gè)函數(shù)中參數(shù)的個(gè)數(shù).
arguments.callee: 指向的是當(dāng)前運(yùn)行的函數(shù).callee是arguments對(duì)象的屬性。
在該函數(shù)的函數(shù)體內(nèi),它可以指向當(dāng)前正在執(zhí)行的函數(shù).當(dāng)函數(shù)是匿名函數(shù)時(shí),這是很有用的,比如沒(méi)有名字的函數(shù)表達(dá)式(也被叫做"匿名函數(shù)").
詳細(xì)解釋可以看這里arguments.callee.我們可以看一下下面的例子:
function hello() { return function() { console.log("hello"); if(!arguments.length) { console.log("from a anonymous function."); return arguments.callee; } } } hello()(1); // hello /* * hello * from a anonymous function. * hello * from a anonymous function. */ hello()()();
fn.caller: 返回調(diào)用指定函數(shù)的函數(shù).詳細(xì)的解釋可以看這里Function.caller,下面是示例代碼:
function hello() { console.log("hello"); console.log(hello.caller); } function callHello(fn) { return fn(); } callHello(hello); // hello [Function: callHello]
高階函數(shù)(high-order function)
高階函數(shù)就是操作函數(shù)的函數(shù),它接受一個(gè)或多個(gè)函數(shù)作為參數(shù),并返回一個(gè)新的函數(shù).
我們來(lái)看一個(gè)例子,來(lái)幫助我們理解這個(gè)概念.就舉一個(gè)我們高中經(jīng)常遇到的場(chǎng)景,如下:
f1(x, y) = x + y; f2(x) = x * x; f3 = f2(f3(x, y));
我們來(lái)實(shí)現(xiàn)f3函數(shù),看看應(yīng)該如何實(shí)現(xiàn),具體的代碼如下所示:
function f1(x, y) { return x + y; } function f2(x) { return x * x; } function func3(func1, func2) { return function() { return func2.call(this, func1.apply(this, arguments)); } } var f3 = func3(f1, f2); console.log(f3(2, 3)); // 25
我們通過(guò)函數(shù)func3將函數(shù)f1,f2結(jié)合到了一起,然后返回了一個(gè)新的函數(shù)f3;這個(gè)函數(shù)就是我們期望的那個(gè)函數(shù).
不完全函數(shù)(partial function)
什么是不完全函數(shù)呢?所謂的不完全函數(shù)和我們上面所說(shuō)的柯里化基本差不多;所謂的不完全函數(shù),就是給你想要運(yùn)行的那個(gè)函數(shù)綁定一個(gè)固定的參數(shù)值;
然后后面的運(yùn)行或者說(shuō)傳遞參數(shù)都是在前面的基礎(chǔ)上進(jìn)行運(yùn)行的.看下面的例子:
// 一個(gè)將函數(shù)的arguments對(duì)象變成一個(gè)數(shù)組的方法 function array(a, n) { return Array.prototype.slice.call(a, n || 0); } // 我們要運(yùn)行的函數(shù) function showMsg(a, b, c){ return a * (b - c); } function partialLeft(f) { var args = arguments; return function() { var a = array(args, 1); a = a.concat(array(arguments)); console.log(a); // 打印實(shí)際傳遞到函數(shù)中的參數(shù)列表 return f.apply(this, a); } } function partialRight(f) { var args = arguments; return function() { var a = array(arguments); a = a.concat(array(args, 1)); console.log(a); // 打印實(shí)際傳遞到函數(shù)中的參數(shù)列表 return f.apply(this, a); } } function partial(f) { var args = arguments; return function() { var a = array(args, 1); var i = 0; j = 0; for(; i < a.length; i++) { if(a[i] === undefined) { a[i] = arguments[j++]; } } a = a.concat(array(arguments, j)); console.log(a); // 打印實(shí)際傳遞到函數(shù)中的參數(shù)列表 return f.apply(this, a); } } partialLeft(showMsg, 1)(2, 3); // 實(shí)際參數(shù)列表: [1, 2, 3] 所以結(jié)果是 1 * (2 - 3) = -1 partialRight(showMsg, 1)(2, 3); // 實(shí)際參數(shù)列表: [2, 3, 1] 所以結(jié)果是 2 * (3 - 1) = 4 partial(showMsg, undefined, 1)(2, 3); // 實(shí)際參數(shù)列表: [2, 1, 3] 所以結(jié)果是 2 * (1 - 3) = -4一些你可能會(huì)喜歡的JS庫(kù)
JavaScript的柯里化與JavaScript的函數(shù)式編程密不可分,下面列舉了一些關(guān)于JavaScript函數(shù)式編程的庫(kù),大家可以看一下:
underscore
lodash
ramda
bacon.js
fn.js
functional-js
歡迎提意見(jiàn):可以在這里提意見(jiàn)
參考的資料Gettin’ Freaky Functional w/Curried JavaScript
A Beginner’s Guide to Currying in Functional JavaScript
Currying, Spice Up Your Javascript Functions
Curried JavaScript functions
Tidying Up a JavaScript Application with Higher-Order Functions
Currying Functions in Javascript
JavaScript 中的函數(shù)式編程實(shí)踐
函數(shù)式JavaScript(4):函數(shù)柯里化
前端開(kāi)發(fā)者進(jìn)階之函數(shù)柯里化Currying
JS中的柯里化(currying)
淺析JavaScript中的函數(shù)currying柯里化
Js函數(shù)柯里化
深入解析JavaScript中函數(shù)的Currying柯里化
js基礎(chǔ)篇之——JavaScript的柯里化函數(shù)詳解
JS函數(shù)柯里化及其應(yīng)用
JS閉包與柯里化
JavaScript函數(shù)柯里化詳解
Javascript curry - what are the practical applications?
Currying and Partial Functions in JavaScript
What is "Currying"?
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/86459.html
摘要:而柯里化是一個(gè)屬于函數(shù)式編程的一個(gè)常見(jiàn)的技巧。簡(jiǎn)單來(lái)說(shuō),函數(shù)柯里化就是對(duì)高階函數(shù)的降階處理。讓你意外的是,這就是柯里化的基本思想,簡(jiǎn)單地讓人猝不及防。 函數(shù)式編程是一種被部分JavaScript程序員推崇的編程風(fēng)格,更別說(shuō) Haskell 和 Scala 這種以函數(shù)式為教義的語(yǔ)言。原因是因?yàn)槠淠苡幂^短的代碼實(shí)現(xiàn)功能,如果掌握得當(dāng),能達(dá)到代碼文檔化(代碼本身具有很高可讀性甚至可以代替文檔...
摘要:如果你對(duì)函數(shù)式編程有一定了解,函數(shù)柯里化是不可或缺的,利用函數(shù)柯里化,可以在開(kāi)發(fā)中非常優(yōu)雅的處理復(fù)雜邏輯。同樣先看簡(jiǎn)單版本的方法,以方法為例,代碼來(lái)自高級(jí)程序設(shè)計(jì)加強(qiáng)版實(shí)現(xiàn)上面函數(shù),可以換成任何其他函數(shù),經(jīng)過(guò)函數(shù)處理,都可以轉(zhuǎn)成柯里化函數(shù)。 我們經(jīng)常說(shuō)在Javascript語(yǔ)言中,函數(shù)是一等公民,它們本質(zhì)上是十分簡(jiǎn)單和過(guò)程化的。可以利用函數(shù),進(jìn)行一些簡(jiǎn)單的數(shù)據(jù)處理,return 結(jié)果,...
摘要:作為函數(shù)式編程語(yǔ)言,帶來(lái)了很多語(yǔ)言上的有趣特性,比如柯里化和反柯里化。在一些函數(shù)式編程語(yǔ)言中,會(huì)定義一個(gè)特殊的占位變量。個(gè)人理解不知道對(duì)不對(duì)延遲執(zhí)行柯里化的另一個(gè)應(yīng)用場(chǎng)景是延遲執(zhí)行。不斷的柯里化,累積傳入的參數(shù),最后執(zhí)行。作為函數(shù)式編程語(yǔ)言,JS帶來(lái)了很多語(yǔ)言上的有趣特性,比如柯里化和反柯里化。 這里可以對(duì)照另外一篇介紹 JS 反柯里化 的文章一起看~ 1. 簡(jiǎn)介 柯里化(Currying)...
摘要:函數(shù)柯里化是把支持多個(gè)參數(shù)的函數(shù)變成接收單一參數(shù)的函數(shù),并返回一個(gè)函數(shù)能接收處理剩余參數(shù),而反柯里化就是把參數(shù)全部釋放出來(lái)。但在一些復(fù)雜的業(yè)務(wù)邏輯封裝中,函數(shù)柯里化能夠?yàn)槲覀兲峁└玫膽?yīng)對(duì)方案,讓我們的函數(shù)更具自由度和靈活性。 showImg(https://segmentfault.com/img/bVburN1?w=800&h=600); 柯里化(Curring, 以邏輯學(xué)家Has...
摘要:作為函數(shù)式編程語(yǔ)言,帶來(lái)了很多語(yǔ)言上的有趣特性,比如柯里化和反柯里化。個(gè)人理解不知道對(duì)不對(duì)延遲執(zhí)行柯里化的另一個(gè)應(yīng)用場(chǎng)景是延遲執(zhí)行。不斷的柯里化,累積傳入的參數(shù),最后執(zhí)行。 作為函數(shù)式編程語(yǔ)言,JS帶來(lái)了很多語(yǔ)言上的有趣特性,比如柯里化和反柯里化。 這里可以對(duì)照另外一篇介紹 JS 反柯里化 的文章一起看~ 1. 簡(jiǎn)介 柯里化(Currying),又稱(chēng)部分求值(Partial Evalu...
閱讀 1640·2023-04-25 20:36
閱讀 2049·2021-09-02 15:11
閱讀 1177·2021-08-27 13:13
閱讀 2653·2019-08-30 15:52
閱讀 4588·2019-08-29 17:13
閱讀 1001·2019-08-29 11:09
閱讀 1491·2019-08-26 11:51
閱讀 833·2019-08-26 10:56