您的位置:首頁>正文

前端開發進階之函數柯裡化

概念:只傳遞給函數一部分參數來調用, 讓它返回一個函數去處理剩下的參數

開篇之前, 我們先來看一個例子

function square(i) { return i * i;}function double(i) return i * 2;}function map(handeler, list) { return list.map(handeler)}// 陣列的每一項平方map(square, [1, 2, 3, 4, 5]);map(square, [6, 7, 8, 9, 10]);// 陣列的每一項加倍map(dubble, [1, 2, 3, 4, 5]);map(dubble, [6, 7, 8, 9, 10]);

例子中,

創建了一個通知函數 map,用於適應不同的應用場景。 顯然, 通用性不用懷疑。 同時, 例子中重複傳入了相同的處理函數:square和dubble。

實際開發中, 我們經常會用到類似的方法來實現我們功能上的需求。 這樣寫能用性是有了, 但是這種通用性的增強必然帶來適用性的減弱。 所以, 我們需要在中間找到一種平衡。

好了, 到這裡我們可以看一下currying的簡單實現了

var add = function(x) { return function(y) { return x + y; };};var increment = add(1);var addTen = add(10);increment(2);// 3addTen(2);// 12

這裡我們定義了一個 add 函數, 它接受一個參數並返回一個新的函數。 調用 add 之後, 返回的函數就通過閉包的方式記住了 add 的第一個參數。 一次性地調用它實在是有點繁瑣, 好在我們可以使用一個特殊的 curry説明函數(helper function)使這類函數的定義和調用更加容易。

這就是currying, 到這裡什麼是函數柯裡化相信大家已經有一定的概念了。 但我們更希望的是能有一個函數幫我們把所有需要進行柯裡化的函數進行處理。 所以……

我們來看一下currying的通用實現吧

function currying(fn) { var slice = Array.prototype.slice, _args = slice.call(argumengs, 1); return function() { var _inargs = slice.call(arguments); return fn.apply(null, _args.concat(_inargs) }}

下面我們利用柯裡化改造一下:

function square(i) { return i * i;}function dubble(i) { return i *= 2;}function map(handeler, list) { return list.map(handeler);}var mapSQ = currying(map, square);mapSQ([1, 2, 3, 4, 5]);mapSQ([6, 7, 8, 9, 10]);var mapDB = currying(map, dubble);mapDB([1, 2, 3, 4, 5]);mapDB([6, 7, 8, 9, 10]);

例子中, 我們通過currying這個方法來把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數。 並且返回接受餘下的參數而且返回結果。 這也就是我們這次要討論的主題——函數 柯裡化Currying.

柯裡化不僅僅是提高了代碼的合理性, 更重的它突出一種思想---降低適用範圍, 提高適用性。

下面我們來看一下一個範圍更廣也更為大家所熟悉的例子

function Ajax(){ this.xhr = new XMLHttpRequest();}Ajax.prototype.open = function(type, url, data, callback) { this.onload = function() { callback(this.xhr.responseText, this.xhr.status, this.xhr); } this.xhr.open(type, url, data.async); this.xhr.send(data.paras); 'get post'.split(' ').forEach(function(mt) { Ajax.prototype[mt] = currying(Ajax.prototype.open, mt); }}var xhr1 = new Ajax();xhr1.get('url', {}, function(data) { // do some thing})var xhr2 = new Ajax();xhr2.post('url', {}, function(data) { // done(data)})

到這裡, 大家應該就可以理解為什麼我們可以用在用jQuery時可以用ajax.get, ajax.post這樣的方法了吧~

後記:有些事物在你得到之前是無足輕重的, 得到之後就不可或缺了。 微波爐是這樣, 智慧手機是這樣, 互聯網也是這樣——老人們在沒有互聯網的時候過得也很充實。 對我來說, 函數的柯裡化(curry)也是這樣。

作者:被前端耽擱的後端林先生

對於web前端學習有不懂的, 或者不知道學習路線, 不知道學習方法, 不知道該如何扎實能找到工作的朋友, 可以來我們頭條前端群:592569448, 我整理了非常專業的JavaScript、jQuery、bootstrap、angularJS、react、nodejs等企業級框架項目實戰, 還有PDF文檔資料都上傳到網盤了。

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示