摘要:對于函數(shù)的柯里化應(yīng)該不陌生,簡單來說技術(shù)是一種通過把多個(gè)參數(shù)填充到函數(shù)體中,實(shí)現(xiàn)將函數(shù)轉(zhuǎn)換為一個(gè)新的經(jīng)過簡化的使之接受的參數(shù)更少函數(shù)的技術(shù)。
對于函數(shù)的柯里化(currying)應(yīng)該不陌生,簡單來說 Currying 技術(shù)是一種通過把多個(gè)參數(shù)填充到函數(shù)體中,實(shí)現(xiàn)將函數(shù)轉(zhuǎn)換為一個(gè)新的經(jīng)過簡化的(使之接受的參數(shù)更少)函數(shù)的技術(shù)。當(dāng)發(fā)現(xiàn)正在調(diào)用同一個(gè)函數(shù)時(shí),并且傳遞的參數(shù)絕大多數(shù)都是相同的,那么用一個(gè)Curry化的函數(shù)是一個(gè)很好的選擇.
下面利用閉包實(shí)現(xiàn)一個(gè)curry化的加法函數(shù), 我們簡單理解一下 curry 化:
function add(x, y){ if(x && y) return x + y; if(!x && !y) throw Error("Cannot calculate"); return function(newx){ return x + newx; }; } add(3)(4); //7 add(3, 4); //7 var newAdd = add(5); newAdd(8); //13 var add2000 = add(2000); add2000(100); //2100
這樣做其實(shí)很類似 bind:
function add(a, b){ console.log(a+b); return a + b; } add(3, 4); //7 add.bind(null, 3)(4); //7 var newAdd = add.bind(null, 5); newAdd(8); //13 var add2000 = add.bind(null, 2000); add2000(100); //2100
同理也可以使用 call 和 apply, 因?yàn)樗麄兛梢詫?shí)現(xiàn) bind 的功能:
Function.prototype.bind = function(context){ var _this = this; var args = [].slice.call(arguments, 1); return function (){ innerArgs = [].slice.call(arguments); if(innerArgs && innerArgs.length > 0) args.push.apply(args, innerArgs); return _this.apply(context, args); } } add(3, 4); //7 add.bind(null, 3)(4); //7 var newAdd = add.bind(null, 5); newAdd(8); //13 var add2000 = add.bind(null, 2000); add2000(100); //2100
但是,如果看到了這個(gè)題:
實(shí)現(xiàn)一個(gè)函數(shù)sum,運(yùn)算結(jié)果可以滿足如下預(yù)期結(jié)果:
sum(1,2,3); //6 sum(2,3)(2); //7 sum(1)(2)(3)(4); //10 sum(2)(4,1)(2); //9
還覺得簡單么?我們理一下思路。首先試想一下這個(gè) sum 函數(shù)的結(jié)構(gòu):
function sum(){ return function(){ return function(){ //... } } }
這個(gè)函數(shù)返回的一定是個(gè)函數(shù),但貌似需要寫無限個(gè),這個(gè)不合理,我們修改一下:
function sum(){ function innerSum(){ //... return innerSum(); } return innerSum(); }
這樣一來每次調(diào)用就不需要定義無限個(gè)函數(shù)了。我們完善里面的代碼:
//sum(1,2,3); //6 //sum(2,3)(2); //7 //sum(1)(2)(3)(4); //10 //sum(2)(4,1)(2); //9 function sum(){ var cur = [].slice.call(arguments).reduce(function(a,b){return a+b;},0); function innerSum(){ var next = [].slice.call(arguments).reduce(function(a,b){return a+b;},0); cur += next; return innerSum; } return innerSum; }
這樣 sum 函數(shù)的柯里化過程就完成了,但是這個(gè)函數(shù)的返回的總是一個(gè)函數(shù),這樣我們?nèi)绾屋敵鰯?shù)值呢?我們可以借助隱式類型轉(zhuǎn)換需要的 toString 函數(shù)實(shí)現(xiàn):
function sum(){ var cur = [].slice.call(arguments).reduce(function(a,b){return a+b;},0); function innerSum(){ var next = [].slice.call(arguments).reduce(function(a,b){return a+b;},0); cur += next; return innerSum; } innerSum.toString = function(){ return cur; } return innerSum; } console.log(sum(1,2,3)); //6 console.log(sum(2,3)(2)); //7 console.log(sum(1)(2)(3)(4)); //10 console.log(sum(2)(4,1)(2)); //9
計(jì)算結(jié)果沒錯(cuò),我們還可以換作 valueOf 實(shí)現(xiàn):
function sum(){ var cur = [].slice.call(arguments).reduce(function(a,b){return a+b;},0); function innerSum(){ var next = [].slice.call(arguments).reduce(function(a,b){return a+b;},0); cur += next; return innerSum; } innerSum.valueOf = function(){ return cur; } return innerSum; } console.log(sum(1,2,3)); //6 console.log(sum(2,3)(2)); //7 console.log(sum(1)(2)(3)(4)); //10 console.log(sum(2)(4,1)(2)); //9
其實(shí),如果同時(shí)存在 toString 和 valueOf 系統(tǒng)會(huì)先調(diào)用 toString, 然后調(diào)用valueOf,返回值自然是 valueOf 的返回值。這個(gè)很基礎(chǔ),這里就不提了。
通用柯里化方法
通用的柯里化寫法其實(shí)比之前的 sum 函數(shù)要簡單許多
var currying = function(fn) { // 主要還是收集所有需要的參數(shù)到一個(gè)數(shù)組中,便于統(tǒng)一計(jì)算 var args = [].slice.call(arguments, 1); return function(){ var _args = args.concat([].slice.call(arguments)); return fn.apply(null, _args); } } var sum = function(){ var args = [].slice.call(arguments); return args.reduce(function(a, b) { return a + b; }); }; var sum10 = currying(sum, 10); console.log(sum10(20, 10)); // 40 console.log(sum10(10, 5)); // 25
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/107628.html
摘要:忍者秘籍一書中,對于柯里化的定義如下在一個(gè)函數(shù)中首先填充幾個(gè)參數(shù)然后再返回一個(gè)新函數(shù)的技術(shù)稱為柯里化。回到我們的題目本身,其實(shí)根據(jù)測試用例我們可以發(fā)現(xiàn),函數(shù)的要求就是接受單一函數(shù),例如但是與柯里化不同之處在于,柯里化返回的一個(gè)新函數(shù)。 歡迎大家再一次來到我的文章專欄:從面試題中我們能學(xué)到什么,各位同行小伙伴是否已經(jīng)開始了悠閑的春節(jié)假期呢?在這里提前祝大家雞年大吉吧~哈哈,之前有人說...
摘要:函數(shù)柯里化在函數(shù)式編程中,函數(shù)是一等公民。函數(shù)柯里化的主要作用和特點(diǎn)就是參數(shù)復(fù)用提前返回和延遲執(zhí)行。可能在實(shí)際應(yīng)用場景中,很少使用函數(shù)柯里化的解決方案,但是了解認(rèn)識(shí)函數(shù)柯里化對自身的提升還是有幫助的。 最近在整理面試資源的時(shí)候,發(fā)現(xiàn)一道有意思的題目,所以就記錄下來。 題目 如何實(shí)現(xiàn) multi(2)(3)(4)=24? 首先來分析下這道題,實(shí)現(xiàn)一個(gè) multi 函數(shù)并依次傳入?yún)?shù)執(zhí)行,...
摘要:函數(shù)柯里化關(guān)于函數(shù)柯里化的問題最初是在忍者秘籍中講閉包的部分中看到的,相信很多同學(xué)見過這樣一道和柯里化有關(guān)的面試題實(shí)現(xiàn)一個(gè)函數(shù),使得如下斷言能夠能夠通過簡單說就是實(shí)現(xiàn)一個(gè)求值函數(shù),能夠?qū)⑺袇?shù)相加得出結(jié)果。方法返回一個(gè)表示該對象的字符串。 函數(shù)柯里化 ??關(guān)于函數(shù)柯里化的問題最初是在《JavaScript忍者秘籍》中講閉包的部分中看到的,相信很多同學(xué)見過這樣一道和柯里化有關(guān)的面試題:...
摘要:原題如下寫一個(gè)方法,當(dāng)使用下面的語法調(diào)用時(shí),能正常工作這道題要考察的,就是對函數(shù)柯里化的理解。當(dāng)參數(shù)只有一個(gè)的時(shí)候,進(jìn)行柯里化的處理。這其實(shí)就是函數(shù)柯里化的簡單應(yīng)用。 showImg(https://segmentfault.com/img/bVbopGm?w=620&h=350); 前言 這是前端面試題系列的第 6 篇,你可能錯(cuò)過了前面的篇章,可以在這里找到: ES6 中箭頭函數(shù)的...
閱讀 2946·2023-04-25 22:16
閱讀 2092·2021-10-11 11:11
閱讀 3247·2019-08-29 13:26
閱讀 593·2019-08-29 12:32
閱讀 3409·2019-08-26 11:49
閱讀 2987·2019-08-26 10:30
閱讀 1938·2019-08-23 17:59
閱讀 1506·2019-08-23 17:57