下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、前端JavaScript徹底弄懂函數(shù)柯化curry錄、什么是柯化( curry)、柯化的途三、如何封裝柯化具函數(shù)、什么是柯化(在數(shù)學和計算機科學中,柯化是種將使多個參數(shù)的個函數(shù)轉(zhuǎn)換成系列使個參數(shù)的函數(shù)的技術(shù)。舉例來說,個接收3個參數(shù)的普通函數(shù),在進柯化后, 柯化版本的函數(shù)接收個參數(shù)并返回接收下個參數(shù)的函數(shù), 該函數(shù)返回個接收第三個參數(shù)的函數(shù)。最后個函數(shù)在接收第三個參數(shù)后, 將之前接收到的三個參數(shù)應(yīng)于原普通函數(shù)中,并返回最終結(jié)果。數(shù)學和計算科學中的柯化:/ 數(shù)學和計算科學中的柯化:/個接收三個參數(shù)的普通函數(shù)function sum(a,b,c) console.log(a+b+c)/于將普通函數(shù)
2、轉(zhuǎn)化為柯化版本的具函數(shù)function curry(fn) /. 內(nèi)部實現(xiàn)省略,返回個新函數(shù)/獲取個柯化后的函數(shù)let _sum = curry(sum);/返回個接收第個參數(shù)的函數(shù)let A = _sum(1);/返回個接收第三個參數(shù)的函數(shù)let B = A(2);/接收到最后個參數(shù),將之前所有的參數(shù)應(yīng)到原函數(shù)中,并運B(3)/ print : 6對于Javascript 語來說,我們通常說的柯化函數(shù)的概念,與數(shù)學和計算機科學中的柯化的概念并不完全樣。在數(shù)學和計算機科學中的柯化函數(shù),次只能傳遞個參數(shù);我們Javascript 實際應(yīng)中的柯化函數(shù),可以傳遞個或多個參數(shù)。來看這個例:/普通函數(shù)f
3、unction fn(a,b,c,d,e) console.log(a,b,c,d,e)/成的柯化函數(shù)let _fn = curry(fn);_fn(1,2,3,4,5);/ print: 1,2,3,4,5_fn(1)(2)(3,4,5); / print: 1,2,3,4,5_fn(1,2)(3,4)(5); / print: 1,2,3,4,5_fn(1)(2)(3)(4)(5); / print: 1,2,3,4,5對于已經(jīng)柯化后的 _fn 函數(shù)來說,當接收的參數(shù)數(shù)量與原函數(shù)的形參數(shù)量相同時,執(zhí)原函數(shù);當接收的參數(shù)數(shù)量于原函數(shù)的形參數(shù)量時,返回個函數(shù)于接收剩余的參數(shù),直接收的參數(shù)數(shù)量與
4、形參數(shù)量致,執(zhí)原函數(shù)。當我們知道柯化是什么了的時候,我們來看看柯化到底有什么?、柯化的途柯化實際是把簡答的問題復(fù)雜化了,但是復(fù)雜化的同時,我們在使函數(shù)時擁有了更加多的由度。這對于函數(shù)參數(shù) 的由處理,正是柯化的核所在??禄举|(zhì)上是降低通性,提適性。來看個例:我們作中會遇到各種需要通過正則檢驗的需求,如校驗電話號碼、校驗郵箱、校驗份證號、校驗密碼等,這時我們會 封裝個通函數(shù) checkByRegExp ,接收兩個參數(shù),校驗的正則對象和待校驗的字符串function checkByRegExp(regExp,string) return regExp.test(string);checkByRegE
5、xp(/1d10$/,; / 校驗電話號碼checkByRegExp(/(w)+(.w+)*(w)+(.w+)+)$/, ); / 校驗郵箱上這段代碼,乍看沒什么問題,可以滿我們所有通過正則檢驗的需求。但是我們考慮這樣個問題,如果我們需要校 驗多個電話號碼或者校驗多個郵箱呢?我們可能會這樣做:checkByRegExp(/1d10$/,; / 校驗電話號碼checkByRegExp(/1d10$/,; / 校驗電話號碼checkByRegExp(/1d10$/,; / 校驗電話號碼check
6、ByRegExp(/(w)+(.w+)*(w)+(.w+)+)$/, ); / 校驗郵箱checkByRegExp(/(w)+(.w+)*(w)+(.w+)+)$/, test); / 校驗郵箱checkByRegExp(/(w)+(.w+)*(w)+(.w+)+)$/, test); / 校 驗 郵 箱我們每次進校驗的時候都需要輸串正則,再校驗同類型的數(shù)據(jù)時,相同的正則我們需要寫多次,這就導致我們在使的時候效率低下,并且由于checkByRegExp 函數(shù)本是個具函數(shù)并沒有任何意義, 段時間后我們重新來看這些代碼時,如果沒有注釋,我們必須通過檢查正則的內(nèi)容, 我們才能知道我們校驗的是電話號碼
7、還是郵箱,還是別的什么。此時,我們可以借助柯化對checkByRegExp 函數(shù)進封裝,以簡化代碼書寫,提代碼可讀性。/進柯化let _check = curry(checkByRegExp);/成具函數(shù),驗證電話號碼let checkCellPhone = _check(/1d10$/);/成具函數(shù),驗證郵箱let checkEmail = _check(/(w)+(.w+)*(w)+(.w+)+)$/);checkCellPhone; / checkCellPhone; / checkCellPhone; / c
8、heckEmail(); / 校驗郵箱checkEmail(test); / 校驗郵箱checkEmail(test); / 校驗郵箱再來看看通過柯化封裝后,我們的代碼是不是變得簡潔直觀了呢。經(jīng)過柯化后,我們成了兩個函數(shù)checkCellPhone 和 checkEmail , checkCellPhone 函數(shù)只能驗證傳的字符串是否是電話號碼, checkEmail 函數(shù)只能驗證傳的字符串是否是郵箱, 它們與 原函數(shù) checkByRegExp 相,從功能上通性降低了,但適性提升了。 柯化的這種途可以被理解為:參數(shù)復(fù)我們再來看個例假定我們有這樣段數(shù)據(jù):let list = name:lucy
9、,name:jack我們需要獲取數(shù)據(jù)中的所有 name 屬性的值,常規(guī)思路下,我們會這樣實現(xiàn):let names = list.map(function(item) return ;)那么我們?nèi)绾慰禄乃季S來實現(xiàn)呢let prop = curry(function(key,obj) return objkey;)let names = list.map(prop(name)看到這,可能會有疑問,這么簡單的例,僅僅只是為了獲取name 的屬性值,為何還要實現(xiàn)個prop 函數(shù)呢,這樣太煩了吧。我們可以換個思路,prop 函數(shù)實現(xiàn)次后,以后是可以多次使的,所以我們在考慮代碼復(fù)雜程度的時候,是可以將p
10、rop 函數(shù)的實現(xiàn)去掉的。我們實際的代碼可以理解為只有l(wèi)et names = list.map(prop(name)這么看來,通過柯化的式,我們的代碼是不是變得更精簡了,并且可讀性更了呢。三、如何封裝柯化具函數(shù)接下來,我們來思考如何實現(xiàn)curry 函數(shù)?;叵胫拔覀儗τ诳禄亩x,接收部分參數(shù),返回個函數(shù)接收剩余參數(shù),接收夠參數(shù)后,執(zhí)原函數(shù)。 length屬性,獲取函數(shù)的形參個數(shù),形參的個數(shù)就是所需的參數(shù)個數(shù)在調(diào)柯化具函數(shù)時,動指定所需的參數(shù)個數(shù)我們將這兩點結(jié)合以下,實現(xiàn)個簡單curry 函數(shù):/*將函數(shù)柯化param fn待柯化的原函數(shù)param len所需的參數(shù)個數(shù),默認為原函數(shù)的形參個數(shù)
11、*/function curry(fn,len = fn.length) return _curry.call(this,fn,len)/*中轉(zhuǎn)函數(shù)param fn待柯化的原函數(shù)param len所需的參數(shù)個數(shù)param args 已接收的參數(shù)列表*/function _curry(fn,len,.args) return function (.params) let _args = .args,.params; if(_args.length = len)return fn.apply(this,_args);elsereturn _curry.call(this,fn,len,._args
12、)我們來驗證下:let _fn = curry(function(a,b,c,d,e) console.log(a,b,c,d,e);_fn(1,2,3,4,5);/ print: 1,2,3,4,5_fn(1)(2)(3,4,5); / print: 1,2,3,4,5_fn(1,2)(3,4)(5); / print: 1,2,3,4,5_fn(1)(2)(3)(4)(5); / print: 1,2,3,4,5我們常的具庫 lodash 也提供了 curry 法,并且增加了常好玩的placeholder 功能,通過占位符的式來改變傳參數(shù)的順序。如說,我們傳個占位符,本次調(diào)傳遞的參數(shù)略過占
13、位符,占位符所在的位置由下次調(diào)的參數(shù)來填充,如這樣: 直接看下官的例:接下來我們來思考,如何實現(xiàn)占位符的功能。lodash 的curry 函數(shù)來說,curry lodash lodash 對象當做默認占位符來使。我們的實現(xiàn)的 curry 函數(shù),本并沒有掛載在任何對象上,所以將curry 函數(shù)當做默認占位符使占位符,的是改變參數(shù)傳遞的順序,所以在curry 函數(shù)實現(xiàn)中,每次需要記錄是否使了占位符,并且記錄占位符所代表的參數(shù)位置。直接上代碼:/*param fn待柯化的函數(shù)param length需要的參數(shù)個數(shù),默認為函數(shù)的形參個數(shù)param holder占位符,默認當前柯化函數(shù)return Fu
14、nction柯化后的函數(shù)*/function curry(fn,length = fn.length,holder = curry) return _curry.call(this,fn,length,holder,)/*中轉(zhuǎn)函數(shù)param fn柯化的原函數(shù)param length原函數(shù)需要的參數(shù)個數(shù)param holder接收的占位符param args已接收的參數(shù)列表param holders已接收的占位符位置列表return Function繼續(xù)柯化的函數(shù) 或 最終結(jié)果*/function _curry(fn,length,holder,args,holders) return func
15、tion(._args)/ 將參數(shù)復(fù)制份,避免多次操作同函數(shù)導致參數(shù)混亂let params = args.slice();/ 將占位符位置列表復(fù)制份,新增加的占位符增加此let _holders = holders.slice();/ 循環(huán)參,追加參數(shù) 或 替換占位符_args.forEach(arg,i)=/ 真實參數(shù) 之前存在占位符 將占位符替換為真實參數(shù)if (arg != holder & holders.length) let index = holders.shift();_holders.splice(_holders.indexOf(index),1); paramsinde
16、x = arg;/ 真實參數(shù) 之前不存在占位符 將參數(shù)追加到參數(shù)列表中else if(arg != holder & !holders.length) params.push(arg);/ 傳的是占位符,之前不存在占位符 記錄占位符的位置else if(arg = holder & !holders.length) params.push(arg);_holders.push(params.length - 1);/ 傳的是占位符,之前存在占位符 刪除原占位符位置else if(arg = holder & holders.length) holders.shift(););/ params
17、中前 length 條記錄中不包含占位符,執(zhí)函數(shù)if(params.length = length & params.slice(0,length).every(i=i!=holder) return fn.apply(this,params);elsereturn _curry.call(this,fn,length,holder,params,_holders)驗證下:let fn = function(a, b, c, d, e) console.log(a, b, c, d, e);let _ = ; / 定義占位符let _fn = curry(fn,5,_); / 將函數(shù)柯化,指定所需的參數(shù)個數(shù),指定所需的占位符_fn(1, 2, 3, 4, 5);/ print: 1,2,3,4,5_fn(_, 2, 3, 4, 5
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年租車服務(wù)合同(個人版)
- 2024年度醫(yī)療服務(wù)質(zhì)量評價體系合作協(xié)議3篇
- 課題申報書:大國工匠培養(yǎng)視域下高職畢業(yè)生就業(yè)力模型構(gòu)建與提升路徑
- 2024年餐飲業(yè)股權(quán)交易協(xié)議范本版
- 2024年環(huán)保設(shè)施運營項目員工聘用及環(huán)保技術(shù)服務(wù)合同
- 2024年離婚雙方協(xié)商一致合同書樣本版B版
- 2024年糕點供應(yīng)框架協(xié)議3篇
- 2025年度ROHS環(huán)保產(chǎn)品研發(fā)與生產(chǎn)保證協(xié)議
- 2024年財產(chǎn)分配合同:適用于離婚后的財產(chǎn)規(guī)劃
- 2024年知名品牌與零售商之間的產(chǎn)品銷售合同
- GB/T 12467.5-2009金屬材料熔焊質(zhì)量要求第5部分:滿足質(zhì)量要求應(yīng)依據(jù)的標準文件
- GB 17740-1999地震震級的規(guī)定
- 安全生產(chǎn)事故舉報獎勵制度
- 冠心病健康教育完整版課件
- 永久避難硐室安裝施工組織措施
- 元旦節(jié)前安全教育培訓-教學課件
- 國家開放大學《理工英語1》單元自測8試題答案
- 芯片工藝流程課件1
- 人教版八年級下冊生物期末測試卷帶答案
- 《尖利的物體會傷人》安全教育課件
- 大學生自主創(chuàng)業(yè)證明模板
評論
0/150
提交評論