反柯里化
創(chuàng)新互聯(lián)成立于2013年,先為兗州等服務(wù)建站,兗州等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為兗州企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
相反,反柯里化的作用在與擴(kuò)大函數(shù)的適用性,使本來作為特定對象所擁有的功能的函數(shù)可以被任意對象所用.
即把如下給定的函數(shù)簽名,
obj.func(arg1, arg2)
轉(zhuǎn)化成一個(gè)函數(shù)形式,簽名如下:
func(obj, arg1, arg2)
這就是 反柯里化的形式化描述。
例如,下面的一個(gè)簡單實(shí)現(xiàn):
Function.prototype.uncurrying = function() { var that = this; return function() { return Function.prototype.call.apply(that, arguments); } }; function sayHi () { return "Hello " + this.value +" "+[].slice.call(arguments); } var sayHiuncurrying=sayHi.uncurrying(); console.log(sayHiuncurrying({value:'world'},"hahaha"));
解釋:
最后,我們反過來看,其實(shí)反柯里化相當(dāng)于把原來 sayHi(args) 的形式,轉(zhuǎn)換成了 sayHiuncurrying(obj,args),使得sayHi的使用范圍泛化了。 更抽象地表達(dá), uncurryinging反柯里化,使得原來 x.y(z) 調(diào)用,可以轉(zhuǎn)成 y(x',z) 形式的調(diào)用 。 假設(shè)x' 為x或者其他對象,這就擴(kuò)大了函數(shù)的使用范圍。
通用反柯里化函數(shù)
上面例子中把uncurrying寫進(jìn)了prototype,這不太好,我們其實(shí)可以把 uncurrying 單獨(dú)封裝成一個(gè)函數(shù);
var uncurrying= function (fn) { return function () { var args=[].slice.call(arguments,1); return fn.apply(arguments[0],args); } };
上面這個(gè)函數(shù)很清晰直接。
使用時(shí) 調(diào)用 uncurrying 并傳入一個(gè)現(xiàn)有函數(shù) fn, 反柯里化函數(shù)會返回一個(gè)新函數(shù),該新函數(shù)接受的第一個(gè)實(shí)參將綁定為 fn 中 this的上下文,其他參數(shù)將傳遞給 fn 作為參數(shù)。
所以,對反柯里化更通俗的解釋可以是 函數(shù)的借用,是函數(shù)能夠接受處理其他對象,通過借用泛化、擴(kuò)大了函數(shù)的使用范圍。
所以 uncurrying更常見的用法是對 Javascript 內(nèi)置的其他方法的 借調(diào) 而不用自己都去實(shí)現(xiàn)一遍。
文字描述比較繞,還是繼續(xù)看代碼:
var test="a,b,c"; console.log(test.split(",")); var split=uncurrying(String.prototype.split); //[ 'a', 'b', 'c' ] console.log(split(test,',')); //[ 'a', 'b', 'c' ]
split=uncurrying(String.prototype.split) 給 uncurrying 傳入一個(gè)具體的fn,即String.prototype.split ,split 函數(shù)就具有了 String.prototype.split 的功能,函數(shù)調(diào)用 split(test,',') 時(shí),傳入的第一個(gè)參數(shù)為 split 執(zhí)行的上下文,剩下的參數(shù)相當(dāng)于傳給原 String.prototype.split 函數(shù)。
再看一個(gè)例子:
var $ = {}; console.log($.push); // undefined var pushUncurrying = uncurrying(Array.prototype.push); $.push = function (obj) { pushUncurrying(this,obj); }; $.push('first'); console.log($.length); // 1 console.log($[0]); // first console.log($.hasOwnProperty('length')); // true
這里模仿了一個(gè)“類似jquery庫” 實(shí)現(xiàn)時(shí)借用 Array 的 push 方法。 我們知道對象是沒有 push 方法的,所以 console.log(obj.push) 返回 undefined,可以借用Array 來處理 push,由原生的數(shù)組方法(js引擎)來維護(hù) 偽數(shù)組對象的 length 屬性和數(shù)組成員。
同樣的道理,我們還可以繼續(xù)有:
var indexof=uncurrying(Array.prototype.indexOf); $.indexOf = function (obj) { return indexof(this,obj); }; $.push("second"); console.log($.indexOf('first')); // 0 console.log($.indexOf('second')); // 1 console.log($.indexOf('third')); // -1
例如我們在實(shí)現(xiàn)自己的類庫時(shí),有些方法如果有些方法和原生的類似,那么可以通過 uncurrying 借用原生方法。
我們還可以把 Function.prototype.call/apply 方法 uncurring,例如:
var call= uncurrying(Function.prototype.call); var fn= function (str) { console.log(this.value+str); }; var obj={value:"Foo "}; call(fn, obj,"Bar!"); // Foo Bar!
這樣可以非常靈活地把函數(shù)也當(dāng)做一個(gè)普通“數(shù)據(jù)”來使用,有函數(shù)式編程的趕腳,在一些類庫中經(jīng)常能看到這樣的用法。
通用 uncurrying 函數(shù)的進(jìn)擊
上面的 uncurrying 函數(shù)是比較符合思維習(xí)慣容易理解的版本,接下來一路進(jìn)擊,看幾個(gè)其他版本:
首先,如果B格高一點(diǎn),uncurrying 也可能寫成這樣:
var uncurrying= function (fn) { return function () { var context=[].shift.call(arguments); return fn.apply(context,arguments); } };
當(dāng)然如果還需要再提升B格,那么還可以是這樣:
var uncurrying= function (fn) { return function () { return Function.prototype.call.apply(fn,arguments); } };
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
網(wǎng)站欄目:淺談JS中的反柯里化(uncurrying)
新聞來源:http://muchs.cn/article12/ishddc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、靜態(tài)網(wǎng)站、微信小程序、微信公眾號、網(wǎng)站排名、動態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)