JS中的反柯里化
反柯里化
相反,反柯里化的作用在與擴大函數的適用性,使本來作為特定對象所擁有的功能的函數可以被任意對象所用.
即把如下給定的函數簽名,
obj.func(arg1, arg2)
轉換成函數形式,簽名如下:
func(obj, arg1, arg2)
這就是反柯里化的形式化描述。
例如,下面的一個簡單實作:
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"));
解釋:
#uncurrying是定義在Function的prototype上的方法,因此對所有的函數都可以使用此方法。呼叫時候:sayHiuncurrying=sayHi.uncurrying(),所以uncurrying中的this 指向的是sayHi 函數; (一般原型方法中的this 不是指向原型對象prototype,而是指向調用對象,在這裡調用對像是另一個函數,在javascript中函數也是物件)
call.apply(that, arguments) 把that 設定為call 方法的上下文,然後將arguments 傳給call方法,前文的例子,that 實際指向sayHi,所以呼叫sayHiuncurrying(arg1, arg2, ...) 相當於sayHi.call(arg1, arg2, ...);
sayHi. call(arg1, arg2, ...), call 函式把arg1 當做sayHi的上下文,然後把arg2,... 等剩下的參數傳給sayHi,因此最後相當於arg1.sayHi(arg2,...) ;
因此,這相當於sayHiuncurrying(obj,args) 等於obj.sayHi(args)。
最後,我們反過來看,其實反柯里化相當於把原來sayHi(args) 的形式,轉換成了sayHiuncurrying(obj,args),使得sayHi的使用範圍泛化了。 更抽像地表達, uncurryinging反柯里化,使得原來 x.y(z) 調用,可以轉成 y(x',z) 形式的調用 。 假設x' 為x或其他對象,這就擴大了函數的使用範圍。
通用反柯里化函數
上面例子中把uncurrying寫進了prototype,這不太好,我們其實可以把uncurrying 單獨封裝成一個函數;
var uncurrying= function (fn) { return function () { var args=[].slice.call(arguments,1); return fn.apply(arguments[0],args); } };
上面這個函數很清楚直接。
使用時呼叫uncurrying 並傳入一個現有函數fn, 反柯里化函數會傳回一個新函數,該新函數接受的第一個實參將綁定為fn 中this的上下文,其他參數將傳遞給fn 作為參數。
所以,對反柯里化更通俗的解釋可以是 函數的借用,是函數能夠接受處理其他對象,透過借用泛化、擴大了函數的使用範圍。
所以 uncurrying更常見的用法是對 Javascript 內建的其他方法的 借調 而不用自己都去實作一遍。
文字描述比較繞,還是繼續看程式碼:
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 傳入一個具體的fn,即String.prototype.split ,split 函數就具有了String.prototype.split 的功能,函數呼叫split(test,',') 時,傳入的第一個參數為split 執行的上下文,剩下的參數相當於傳給原String.prototype.split 函數。
再看一個例子:
var $ = {}; console.log($.push); // undefinedvar pushUncurrying = uncurrying(Array.prototype.push); $.push = function (obj) { pushUncurrying(this,obj); }; $.push('first'); console.log($.length); // 1console.log($[0]); // firstconsole.log($.hasOwnProperty('length')); // true
#這裡模仿了一個「類似jquery庫” 實作時藉用Array 的push 方法。 我們知道物件是沒有push 方法的,所以console.log(obj.push) 回傳undefined,可以藉用Array 來處理push,由原生的陣列方法(js引擎)來維護偽數組物件的length 屬性和陣列成員。
同樣的道理,我們還可以繼續有:
var indexof=uncurrying(Array.prototype.indexOf); $.indexOf = function (obj) { return indexof(this,obj); }; $.push("second"); console.log($.indexOf('first')); // 0console.log($.indexOf('second')); // 1console.log($.indexOf('third')); // -1
例如我們在實作自己的類別庫時,有些方法如果有些方法和原生的類似,那麼可以透過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!
這樣可以非常靈活地把函數也當作一個普通「資料」來使用,有函數式程式的趕腳,在一些類別庫中常常能看到這樣的用法。
通用uncurrying 函數的進擊
上面的uncurrying 函數是比較符合思維習慣容易理解的版本,接下來一路進擊,看幾個其他版本:
首先,如果B格高一點,uncurrying 也可能寫成這樣:
var uncurrying= function (fn) { return function () { var context=[].shift.call(arguments); return fn.apply(context,arguments); } };
當然如果還需要再提升B格,那麼還可以是這樣:
var uncurrying= function (fn) { return function () { return Function.prototype.call.apply(fn,arguments); } };
以上是JS中的反柯里化的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務
