JS函數(shù)柯里化

在正式聊函數(shù)柯里化之前,我這里給大家補充下高階函數(shù)的概念和應(yīng)用:

1.1、什么是高階函數(shù)?
高階函數(shù)英文叫 Higher-order function,它的定義很簡單,就是至少滿足下列一個條件的函數(shù):

接受一個或多個函數(shù)作為輸入
輸出一個函數(shù)
也就是說高階函數(shù)是對其他函數(shù)進行操作的函數(shù),可以將它們作為參數(shù)傳遞,或者是返回它們。 簡單來說,高階函數(shù)是一個接收函數(shù)作為參數(shù)傳遞或者將函數(shù)作為返回值輸出的函數(shù)。

1.2、高階函數(shù)例子
其實平時開發(fā)中經(jīng)常會用到高階函數(shù),只是之前你不清楚其概念而已,來看下下面幾個函數(shù):

Array.prototype.map
Array.prototype.filter
Array.prototype.reduce
Array.prototype.sort
這三個數(shù)組的方法函數(shù)就是高階函數(shù),因為它們都接收一個回調(diào)函數(shù)作為參數(shù),滿足第一個條件

高階函數(shù)其中一個優(yōu)點就是在某種情況下可以讓代碼更加簡潔,我們就拿map方法來舉例,如果不用map這個高階方法的話,要實現(xiàn)對一個現(xiàn)有數(shù)組中每個元素*2的需求

不使用高階函數(shù):

const arr1 = [1, 2, 3, 4];
const arr2 = [];
for (let i = 0; i < arr1.length; i++) {
arr2.push( arr1[i] * 2);
}
console.log( arr2 );
// [2, 4, 6, 8]
console.log( arr1 );
// [1, 2, 3, 4]

使用map高階函數(shù):

const arr1 = [1, 2, 3, 4];
const arr2 = arr1.map(item => item * 2);
console.log( arr2 );
// [2, 4, 6, 8]
console.log( arr1 );
// [1, 2, 3, 4]

從上面例子中不難看出用map方法可以輕松實現(xiàn)上述需求,其他兩個方法其實也是同樣的道理,這里就不多敘述了

二、函數(shù)柯里化
2.1、定義
函數(shù)柯里化又叫部分求值,維基百科中對柯里化 (Currying) 的定義為:

在數(shù)學(xué)和計算機科學(xué)中,柯里化是一種將使用多個參數(shù)的函數(shù)轉(zhuǎn)換成一系列使用一個參數(shù)的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。

用大白話來說就是只傳遞給函數(shù)一部分參數(shù)來調(diào)用它,讓它返回一個新函數(shù)去處理剩下的參數(shù)

相信部分同學(xué)看完這個概念還是有點稀里糊涂,我們來看個簡單例子說明下

function url (a,b,c){
return ${a}://www.$.${c}
}
const url1 = url('https',"baidu",'com')
console.log(url1) // "https://www.baidu.com"

上面這個url函數(shù)接受三個參數(shù),最終函數(shù)返回一個完整的url地址,這是普通寫法,然后我們來看下函數(shù)柯里化后的寫法是怎么樣的?

function url(a){
return (b)=>{
return (c)=>{
return ${a}://www.$.${c}
}
}
}
const AA = url('https') // 他是一個函數(shù)
const BB = AA('baidu') // 他是一個函數(shù)
const CC = BB('com') // 他是一個函數(shù)
console.log(CC) // "https://www.baidu.com"

看到這我們再回過頭來看下其概念定義,原先url函數(shù)接受多個參數(shù),然后使用了柯里化技術(shù),將其轉(zhuǎn)換成了一系列接收一個參數(shù)的函數(shù)(url改寫后內(nèi)部就是返回多個接收單一入?yún)⒌暮瘮?shù)),并且返回接受余下的參數(shù)(url原先的其他參數(shù)b和c現(xiàn)通過其內(nèi)部返回的其他函數(shù)來接收處理了),最終函數(shù)柯里化后還是會返回一個新結(jié)果的函數(shù)(上面例子最終返回的是一個接收參數(shù)c返回最終完整結(jié)果的函數(shù)),現(xiàn)在會不會好理解些了呢

2.2、柯里化的應(yīng)用(優(yōu)點)
1、參數(shù)復(fù)用

還是可以用上面拼接完整url的例子來說明

// DEMO1
//原先的寫法
function url (a,b,c){
return ${a}://www.$.${c}
}
const url1 = url('https','baidu','com')
const url2 = url('https','jingdong','com')

//柯里化處理后
function url(a){
return (b)=>{
return (c)=>{
return ${a}://www.$.${c}
}
}
}
const json1 = url('https');
const url1 = json1('baidu')('com')
const url2 = json1('jindong')('com')

通過對函數(shù)柯里化處理后,在生成多個類似url地址時就可以復(fù)用相同的部分,不用重復(fù)傳相同的參數(shù),起到了參數(shù)復(fù)用的效果,我們還可以再繼續(xù)鞏固下,再來看個例子:

//DEMO2
// 原先正則校驗字符串函數(shù)每次調(diào)用時需要重復(fù)傳入正則表達式,如果正則表達式很長的話,是不是會顯得繁瑣
function check(regexp,str){
return regexp.test(str)
}
const result1 = check(/\d+/,'456') // true
const result2 = check(/\d+/,'asd') // false

// 函數(shù)柯里化后
function check(regexp){
return (str)=>{
return regexp.test(str)
}
}
const temp = check(/\d+/)
const result1 = temp('456') // true
const result2 = temp('asd') // false

2、延遲調(diào)用

js中的bind方法其實底層原理也是應(yīng)用了柯里化技術(shù),我們來看下代碼:

// 下面是bind方法的簡易版代碼
function bind (ctx,...args){
return ()=>{
return this.apply(ctx,args) // 這里的this指的就是調(diào)用bind方法的那個函數(shù)
}
}
var name = "windowName"; //全局name
var age = 22; // 全局age
const obj = {name: 'objName',age:11}
function zhangsan (){
return ${this.name}-${this.age}
}
zhangsan() //'windowName-22'
zhangsan.bind(obj) // ? zhangsan (){return ${this.name}-${this.age}}
zhangsan.bind(obj)() //'objName-11'

說明:從上面bind方法可以看出,調(diào)用bind方法后它只是改變了內(nèi)部this指向,并返回了一個函數(shù),并沒有立即執(zhí)行該函數(shù),如果想要得到結(jié)果,需要再次調(diào)用bind方法返回的那個函數(shù)才行,所以這點也就說明了柯里化函數(shù)有延遲調(diào)用的作用

2.3、手寫萬能柯里化函數(shù)
我們可以這么理解:所謂的柯里化函數(shù),就是封裝「一系列的處理步驟」,通過閉包將參數(shù)集中起來計算,最后再把需要處理的參數(shù)傳進去。那如何實現(xiàn) currying 函數(shù)呢?

實現(xiàn)原理就是「用閉包把傳入?yún)?shù)保存起來,當(dāng)傳入?yún)?shù)的數(shù)量足夠執(zhí)行函數(shù)時,就開始執(zhí)行函數(shù)」。上面延遲計算部分已經(jīng)實現(xiàn)了一個簡化版的 currying 函數(shù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • JS_函數(shù)柯里化 與函數(shù)綁定密切相關(guān)的主體是函數(shù)柯里化(function currying),它用于創(chuàng)建已經(jīng)設(shè)置好...
    learninginto閱讀 652評論 1 7
  • 柯里化: 一個函數(shù)原本有多個參數(shù), 之傳入一個參數(shù), 生成一個新函數(shù), 由新函數(shù)接收剩下的參數(shù)來運行得到結(jié)構(gòu). 為...
    攻城熊閱讀 984評論 2 0
  • 第一次看到柯里化這個詞的時候,還是在看一篇算法相關(guān)的博客提到把函數(shù)柯里化,那時一看這個詞就感覺很高端,實際上當(dāng)你了...
    flowsands閱讀 233,534評論 40 282
  • 函數(shù)柯里化:提高函數(shù)的適用性,同時降低函數(shù)的通用性;其實現(xiàn)方式就是固定一些可以預(yù)期的參數(shù),然后返回一個特定的函數(shù) ...
    大雄的學(xué)習(xí)人生閱讀 2,034評論 0 0
  • 首先看看柯里化到底是什么? 維基百科上說道:柯里化,英語:Currying(果然是滿滿的英譯中的既視感),是把接受...
    指尖跳動閱讀 287評論 0 1

友情鏈接更多精彩內(nèi)容