詳解JS函式柯里化

2022-02-23 15:26:32 字數 2881 閱讀 1751

第一次看到柯里化這個詞的時候,還是在看一篇演算法相關的部落格提到把函式柯里化,那時一看這個詞就感覺很高階,實際上當你了解了後才發現其實就是高階函式的乙個特殊用法。

果然是不管作用怎麼樣都要有個高階的名字才有用。

維基百科上說道:柯里化,英語:currying(果然是滿滿的英譯中的既視感),是把接受多個引數的函式變換成接受乙個單一引數(最初函式的第乙個引數)的函式,並且返回接受餘下的引數而且返回結果的新函式的技術。

看這個解釋有一點抽象,我們就拿被做了無數次示例的add函式,來做乙個簡單的實現。

// 普通的add函式

function add(x, y)

// currying後

function curryingadd(x)

}add(1, 2) // 3

curryingadd(1)(2) // 3

實際上就是把add函式的x,y兩個引數變成了先用乙個函式接收x然後返回乙個函式去處理y引數。現在思路應該就比較清晰了,就是只傳遞給函式一部分引數來呼叫它,讓它返回乙個函式去處理剩下的引數。

但是問題來了費這麼大勁封裝一層,到底有什麼用處呢?沒有好處想讓我們程式設計師多幹事情是不可能滴,這輩子都不可能.

1. 引數復用

// 正常正則驗證字串 reg.test(txt)

// 函式封裝後

function check(reg, txt)

check(/\d+/g, 'test') //false

check(/[a-z]+/g, 'test') //true

// currying後

function curryingcheck(reg)

}var hasnumber = curryingcheck(/\d+/g)

var hasletter = curryingcheck(/[a-z]+/g)

hasnumber('test1') // true

hasnumber('testtest') // false

hasletter('21212') // false

上面的示例是乙個正則的校驗,正常來說直接呼叫check函式就可以了,但是如果我有很多地方都要校驗是否有數字,其實就是需要將第乙個引數reg進行復用,這樣別的地方就能夠直接呼叫hasnumber,hasletter等函式,讓引數能夠復用,呼叫起來也更方便。

2. 提前確認

var on = function(element, event, handler) 

} else

}}var on = (function()

};} else };}

})();

//換一種寫法可能比較好理解一點,上面就是把issupport這個引數給先確定下來了

var on = function(issupport, element, event, handler) else

}

我們在做專案的過程中,封裝一些dom操作可以說再常見不過,上面第一種寫法也是比較常見,但是我們看看第二種寫法,它相對一第一種寫法就是自執行然後返回乙個新的函式,這樣其實就是提前確定了會走哪乙個方法,避免每次都進行判斷。

3. 延遲執行

function.prototype.bind = function (context) 

}

像我們js中經常使用的bind,實現的機制就是currying.

說了這幾點好處之後,發現還有個問題,難道每次使用currying都要對底層函式去做修改,

// 初步封裝

var currying = function(fn)

}

這邊首先是初步封裝,通過閉包把初步引數給儲存下來,然後通過獲取剩下的arguments進行拼接,最後執行需要currying的函式。

但是好像還有些什麼缺陷,這樣返回的話其實只能多擴充套件乙個引數,currying(a)(b)(c)這樣的話,貌似就不支援了(不支援多引數呼叫),一般這種情況都會想到使用遞迴再進行封裝一層。

// 支援多引數傳遞

function progresscurrying(fn, args)

// 引數收集完畢,則執行fn

}}

這邊其實是在初步的基礎上,加上了遞迴的呼叫,只要引數個數小於最初的fn.length,就會繼續執行遞迴。

curry的一些效能問題你只要知道下面四點就差不多了:

其實在大部分應用中,主要的效能瓶頸是在操作dom節點上,這js的效能損耗基本是可以忽略不計的,所以curry是可以直接放心的使用。

// 實現乙個add方法,使計算結果能夠滿足如下預期:

add(1)(2)(3) = 6;

add(1, 2, 3)(4) = 10;

add(1)(2)(3)(4)(5) = 15;

function add() ;

// 利用tostring隱式轉換的特性,當最後執行時隱式轉換,並計算最終的值返回

_adder.tostring = function () );

}return _adder;

}add(1)(2)(3) // 6

add(1, 2, 3)(4) // 10

add(1)(2)(3)(4)(5) // 15

add(2, 6)(1) // 9

詳解JS函式柯里化

第一次看到柯里化這個詞的時候,還是在看一篇演算法相關的部落格提到把函式柯里化,那時一看這個詞就感覺很高階,實際上當你了解了後才發現其實就是高階函式的乙個特殊用法。果然是不管作用怎麼樣都要有個高階的名字才有用。維基百科上說道 柯里化,英語 currying 果然是滿滿的英譯中的既視感 是把接受多個引數...

js函式柯里化

什麼是函式柯里化?在電腦科學中,柯里化 currying 是把接受多個引數的函式變換成接受乙個單一引數 最初函式的第乙個引數 的函式,並且返回接受餘下的引數且返回結果的新函式的技術。這個技術由 christopher strachey 以邏輯學家 haskell curry 命名的,儘管它是 mos...

js 函式柯里化

函式柯里化的主要目的就是為了減少函式傳參,同時將一些固定引數私有化。下面展示一段非常簡單計算圓面積的 來說明函式柯里化的原理 circle函式,接受半徑r和 function circle r,p 通過函式柯里化來簡化circle函式,只傳入半徑就能計算出面積 不管怎麼樣,是不會變的,因此我們將他寫...