JS中的函數柯里化


在函數式編程中柯里化是一個十分重要的概念

那么 什么是柯里化呢?

定義:

只傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩余的參數。這個過程就叫做柯里化。

實例:

// 未柯里化的函數
function add1(x,y,z){
	return x+y+z
}
console.log(add1(10,20,30))

// 柯里化處理的函數
function add2(x){
	return function(y){
		return function(z){
			return x+y+z
		}
	}
}
// 可以化處理的函數可以簡化成
// var sum2 = x=>y=>z=>x+y+z
console.log(add2(10)(20)(30))

光從上面的例子來看的話,就會覺得函數的柯里化沒有必要,
反而更加復雜化了,但其實不是這樣。

在函數式編程中,我們往往希望一個函數處理的問題盡可能的單一,而不是將一大堆的處理過程都交給一個函數來處理。

那么我們就可以將每次傳入的參數在單一的函數中進行處理,處理完后在下一個函數中再使用處理后的結果。

比如我們那上面的案例進行一個修改:傳入的函數分別需要進行如下的處理

  • 第一個參數+2
  • 第二個參數*2
  • 第三個參數**2
function addx(x){
	x=x+2
	return function(y){
		y=y*2
		return function(z){
			z=z**2
			return x+y+z
		}
	}
}

另外一個使用柯里化的場景是可以幫助我們實現復用參數邏輯

makeAdder函數要求我們傳入一個num(當我們需要的時候,可以對num進行一些修改)

function makeAdder(num){
	return function(count){
		return num+count
	}
}

var add5 = makeAdder(5)
add5(10)
add5(100)

var add10 = makeAdder(10)
add10(10)
add10(100)

在這里我們演示一個案例 需求是打印一些日志
(包括時間,類型,信息)

// 普通函數的實現方式
function log(date, type, message) {
  console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]: [${message}]`)
}

// log(new Date(), "DEBUG", "查找到輪播圖的bug")
// log(new Date(), "DEBUG", "查詢菜單的bug")
// log(new Date(), "DEBUG", "查詢數據的bug")

// 柯里化的優化
var log = date => type => message => {
  console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]: [${message}]`)
}

// 如果我現在打印的都是當前時間
var nowLog = log(new Date())
nowLog("DEBUG")("查找到輪播圖的bug")
nowLog("FETURE")("新增了添加用戶的功能")

var nowAndDebugLog = log(new Date())("DEBUG")
nowAndDebugLog("查找到輪播圖的bug")
nowAndDebugLog("查找到輪播圖的bug")
nowAndDebugLog("查找到輪播圖的bug")
nowAndDebugLog("查找到輪播圖的bug")


var nowAndFetureLog = log(new Date())("FETURE")
nowAndFetureLog("添加新功能~")

相信通過上面的總結 大家應該對函數的柯里化的重要性有了一定的認識

那么現在我們在提一個新的需求——我們現在需要一個函數,這個函數能夠將我們傳入的函數自動生成柯里化函數,不需要我們自己再寫一個新的函數

// 柯里化函數的實現
function newCurry(fn){
	function curried(...args){
		// 判斷當前已經接收的參數的個數,與參數fn本身需要接受的參數是否一致
		// 當已經傳入的參數 大於等於 需要的參數的時候,就執行函數
		if(args.length >= fn.length){
			return fn.call(this,...args)
		}else{
			// 當已經傳入的參數沒有達到fn的參數個數的時候,需要返回一個函數繼續來接收參數
			return curried2(...args2){
				// 接收完參數后,需要遞歸調用curried來檢查個數是否已經一致了
				return curried.call(this,args.concat(args2))
			}
		}
	}
	return curried
}

理解組合函數

組合函數是在js開發過程中的一種對函數的技巧、模式

比如我們現在需要對某一個數據進行函數的調用,執行兩個函數fn1和fn2,這兩個函數是依次執行的
如果我們每一次都需要對兩個函數進行調用,操作上就會顯得重復
所以我們可以將兩個函數組合起來,自動依次調用
這個過程就是對函數的組合,我們稱為組合函數

function double(num){
	return num*2
}

function square(num){
	return num**2
}

function compose(fn1,fn2){
	return function(x){
		return fn2(fn1(x))
	}
}

var calcFn = compose(double,square)
console.log(calcFn(10))


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM