您好,登錄后才能下訂單哦!
JavaScript 函數(shù)柯里化的深入淺析?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
柯里化 (Currying)是把接收多個(gè)參數(shù)的原函數(shù)變換成接受一個(gè)單一參數(shù)(原來函數(shù)的第一個(gè)參數(shù)的函數(shù))并返回一個(gè)新的函數(shù),新的函數(shù)能夠接受余下的參數(shù),并返回和原函數(shù)相同的結(jié)果。
ES6的方式實(shí)現(xiàn)柯里化的通用
function currying(fn,...rest1){ return function(...rest2){ //這里用apply 是為把數(shù)組形式的參數(shù)直接傳入原函數(shù) null是因?yàn)椴恍枰淖僼his return fn.apply(null,rest1.concat(rest2)); } }
將一個(gè)sayHello函數(shù)柯里化
function sayHello(name,age,fruit){ console.log(`我叫${name},我${age}歲了,我喜歡吃${fruit}`); } //傳入第一個(gè)參數(shù) let curryingShowMsg = currying(sayHello,'小明'); //執(zhí)行傳入剩余參數(shù) curryingShowMsg(22,'芒果');
反柯里化 和柯里化剛好相反。為了讓方法使用場(chǎng)景更廣,使用反柯里化,可以把原生方法借出來,讓任何對(duì)象擁有原生對(duì)象的方法。
二者的區(qū)別
//柯里化 //function(arg1,arg2) => function(arg1)(arg2); //function(arg1,arg2,...,argn) => function(arg1)(arg2)(...)(argn) //反柯里化 //obj.func(arg1,arg2) => func(obj,arg1,arg2)
ES6實(shí)現(xiàn)一個(gè)反柯里化
function unCurrying(fn){ //tar 是我們借給的對(duì)象 以前需要xxx.fn(xx) 現(xiàn)在就可以fn(xxx,xx) return function(tar,...argu){ return fn.apply(tar,argu); } } //比如我們想把Array.prototype.push方法從原生借出來 let push = unCurrying(Array.prototype.push); //arrguments是我們借給的對(duì)象 push(arguments,4);
函數(shù)柯里化的高階實(shí)現(xiàn) ,上面的函數(shù)只實(shí)現(xiàn)一層簡(jiǎn)單的柯里化 如果實(shí)現(xiàn)完全的柯里化func(xx)(xx)(xx)(xx)的話,我們要反復(fù)嵌套我們的柯里化函數(shù),這里我們實(shí)現(xiàn)一個(gè)更高階的柯里化通用方法。
function curryingHelper(fn,len){ //這里先說個(gè)基本知識(shí)點(diǎn) fn.length 返回的是這個(gè)方法需要傳入的參數(shù)個(gè)數(shù) //這里第一次運(yùn)行時(shí)通過fn.length 后面遞歸都是用的傳入的len len為剩余的參數(shù)個(gè)數(shù) const length = len || fn.length; return function(...rest){ //判斷這次傳入的參數(shù)是否大于等于剩下的參數(shù) 如果不是遞歸返回下一個(gè)方法繼續(xù)傳參 return rest.length >= length ? fn.apply(this,rest) : curryingHelper(currying.apply(this,[fn].concat(rest)),length-rest.length) } } //還是剛才的sayHello 函數(shù) let betterShowMsg = curryingHelper(sayHello); //自動(dòng)控制傳參層數(shù) betterShowMsg('zyx')(22)('葡萄'); betterShowMsg('zyx',22)('葡萄');
柯里化的三種用法
1 參數(shù)的復(fù)用
function Say(name,some){ console.log(name + '說' + some); } //如果我們只想讓zyx說一些東西 let zyxSay = currying(Say,'zyx'); zyxSay('1111');//zyx說1111
2 提高適用性
//通用函數(shù)解決了兼容性的問題,但是同時(shí)在不同場(chǎng)景下,我們可能同一種規(guī)則需要反復(fù)使用 //這就可能會(huì)造成代碼的重復(fù)性 比如 function square(i){ return i*i }//平方 function dubble(i){ return i*2 }//雙倍 function map(handler,list){ //handle 是操作的規(guī)則 list是操作的arrguments return list.map(handler) } map(square,[1,2,3]);//數(shù)組每一項(xiàng)平方 map(dubble,[1,2,3]);//數(shù)組每一項(xiàng)加倍 //這就是通用性 我可以用同一個(gè)函數(shù)做很多不同的操作 //但是如果我們需要大量做平方操作 每次我們都需要傳入方法再傳入數(shù)組就造成的代碼浪費(fèi) //這時(shí)我們通過柯里化提高實(shí)用性 let mapSQ = currying(map,square);//直接定義出來的新的平凡操作函數(shù) mapSQ([1,2,3]);//以后就不用傳入操作方法了
3 延遲執(zhí)行
let add = function(...rest){ //定義一個(gè)閉包保存_args const _args = []; return function cb(...rest){ if(rest.length == 0){ //如果不穿參數(shù)了 也就是add() 說明我們需要最后執(zhí)行函數(shù)了 let res = 0; //累加 console.log(_args); for(let data of _args){ res += data; } return res; }else{ _args.push(...rest); //為了鎖住args 閉包 return _args; } } }() add(1); add(2); let a = add(); console.log(a);//3
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。