淺析JavaScript 函數柯里化
柯里化 (Currying)是把接收多個參數的原函數變換成接受一個單一參數(原來函數的第一個參數的函數)并返回一個新的函數,新的函數能夠接受余下的參數,并返回和原函數相同的結果。
ES6的方式實現柯里化的通用
function currying(fn,...rest1){return function(...rest2){//這里用apply 是為把數組形式的參數直接傳入原函數 null是因為不需要改變thisreturn fn.apply(null,rest1.concat(rest2));}}
將一個sayHello函數柯里化
function sayHello(name,age,fruit){console.log(`我叫${name},我${age}歲了,我喜歡吃${fruit}`);}//傳入第一個參數let curryingShowMsg = currying(sayHello,’小明’);//執行傳入剩余參數curryingShowMsg(22,’芒果’);
反柯里化 和柯里化剛好相反。為了讓方法使用場景更廣,使用反柯里化,可以把原生方法借出來,讓任何對象擁有原生對象的方法。
二者的區別
//柯里化//function(arg1,arg2) => function(arg1)(arg2);//function(arg1,arg2,...,argn) => function(arg1)(arg2)(...)(argn)//反柯里化//obj.func(arg1,arg2) => func(obj,arg1,arg2)
ES6實現一個反柯里化
function unCurrying(fn){//tar 是我們借給的對象 以前需要xxx.fn(xx) 現在就可以fn(xxx,xx)return function(tar,...argu){return fn.apply(tar,argu);}}//比如我們想把Array.prototype.push方法從原生借出來let push = unCurrying(Array.prototype.push);//arrguments是我們借給的對象push(arguments,4);
函數柯里化的高階實現 ,上面的函數只實現一層簡單的柯里化 如果實現完全的柯里化func(xx)(xx)(xx)(xx)的話,我們要反復嵌套我們的柯里化函數,這里我們實現一個更高階的柯里化通用方法。
function curryingHelper(fn,len){//這里先說個基本知識點 fn.length 返回的是這個方法需要傳入的參數個數//這里第一次運行時通過fn.length 后面遞歸都是用的傳入的len len為剩余的參數個數const length = len || fn.length;return function(...rest){//判斷這次傳入的參數是否大于等于剩下的參數 如果不是遞歸返回下一個方法繼續傳參return rest.length >= length ? fn.apply(this,rest): curryingHelper(currying.apply(this,[fn].concat(rest)),length-rest.length)}}//還是剛才的sayHello 函數let betterShowMsg = curryingHelper(sayHello);//自動控制傳參層數betterShowMsg(’zyx’)(22)(’葡萄’);betterShowMsg(’zyx’,22)(’葡萄’);
柯里化的三種用法
1 參數的復用
function Say(name,some){console.log(name + ’說’ + some);}//如果我們只想讓zyx說一些東西let zyxSay = currying(Say,’zyx’);zyxSay(’1111’);//zyx說1111
2 提高適用性
//通用函數解決了兼容性的問題,但是同時在不同場景下,我們可能同一種規則需要反復使用//這就可能會造成代碼的重復性 比如function square(i){ return i*i }//平方function dubble(i){ return i*2 }//雙倍function map(handler,list){//handle 是操作的規則 list是操作的arrgumentsreturn list.map(handler)}map(square,[1,2,3]);//數組每一項平方map(dubble,[1,2,3]);//數組每一項加倍//這就是通用性 我可以用同一個函數做很多不同的操作//但是如果我們需要大量做平方操作 每次我們都需要傳入方法再傳入數組就造成的代碼浪費//這時我們通過柯里化提高實用性let mapSQ = currying(map,square);//直接定義出來的新的平凡操作函數mapSQ([1,2,3]);//以后就不用傳入操作方法了
3 延遲執行
let add = function(...rest){//定義一個閉包保存_argsconst _args = [];return function cb(...rest){if(rest.length == 0){//如果不穿參數了 也就是add() 說明我們需要最后執行函數了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
以上就是淺析JavaScript 函數柯里化的詳細內容,更多關于JavaScript 函數柯里化的資料請關注好吧啦網其它相關文章!
相關文章: