1. 程式人生 > 其它 >實現柯里化

實現柯里化

柯里化是什麼?

把接收多個引數的函式,變成接收一個單一引數(最初函式的第一個函式)的函式,並且返回接受餘下的引數,而且返回的結果的新函式的技術。

如果你固定某些引數,你將得到接收餘下引數的一個函式。

總結:

  • 只傳遞給函式一部分引數來呼叫它,讓它返回一個函式去處理剩餘的引數;
  • 這個過程就稱之為柯里化

例如:

function foo(m, n, x, y) {
	return m + n + x + y;
}
foo(m + n + x + y)

// 柯里化過程
function bar(m) {
	return function(n) {
		return function (x) {
			return function (y) {
				return m + n + x + y;
			}
		}
	}
}
// 呼叫
bar(10)(20)(30)(40)

為什麼要實現柯里化?

在函數語言程式設計中,我們希望一個函式處理的問題儘可能單一,而不是將一大堆的處理過程交給一個函式來處理;

柯里化就可以用來實現這個過程,可以將每次傳入的引數在單一的函式中進行處理,處理完成後在下一個函式中再使用處理後的結果。

例如:

// 實現對錯誤的日誌輸出
/*
var log = function(date) {
    return function(type) {
        return function(message) {
            console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]:[${message}]`)
        }
    }
}
*/

// 利用箭頭函式進行優化
var log = date => type => message => {
	console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]:[${message}]`)
}

var nowlog = log(new Date())
newlog("debug")("查詢到了新的bug")
newlog("info")("https請求成功")

var nowDebuglog = log(new Date())("debug")
nowDebuglog("查詢到了新的bug")
nowDebuglog("首頁資料獲取成功")

用了柯里化後你就會發現,我們可以不必一次性得傳遞函式的所有引數,可以對函式進行定製化的處理。

這可以稱之為函式的單一職責原則,我們可以用過柯里化的設計,在一個函式裡做一件事情。

怎麼實現

實現柯里化主要是用於實現以下兩點:

  • 柯里化後的函式可以分批接收引數。
  • 柯里化的函式會生成新函式,將剩餘的引數返回一個新的函式接收。

柯里化實現:

我們將要對下面這樣一個函式(add)實現柯里化。

function add(num1, num2, num3) {
  console.log(this, num1 + num2 + num3)
}

var curryadd = mjyCurrying(add) // mjyCurrying() 函式將模擬實現柯里化的過程
curryadd(10, 20, 30) // 一次性接收全部引數
curryadd.call('111',10, 20, 30) // 可以通過call改變this指向
curryadd(10)(20)(30) // 分批接收引數
curryadd(10)(20,30) // 分批接收引數

mjyCurrying 函式通過遞迴實現模擬柯里化過程

function mjyCurrying(fn) {

  function curried(...args) {
    // 如果引數第一步就傳遞夠了
    if ( args.length >= fn.length ) {
      // 有可能在呼叫的時候需要改變this指向,我們這裡用進行this的繫結
      return fn.call(this, ...args)
    } else {
      // 引數不夠,需要返回一個新的引數,繼續來接收剩餘的引數(對curried進行回撥)
      function callback_curried(...args2) {
        return curried.call(this, ...args, ...args2)
      }
      return callback_curried
    }
  }
  return curried
}