麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > JavaScript > 正文

淺談JS中的反柯里化( uncurrying)

2019-11-19 15:46:07
字體:
來源:轉載
供稿:網友

反柯里化

相反,反柯里化的作用在與擴大函數的適用性,使本來作為特定對象所擁有的功能的函數可以被任意對象所用.

即把如下給定的函數簽名,

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);  }};

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 色淫视频| 精品亚洲成a人在线观看 | 婷婷久久综合九色综合色多多蜜臀 | 国产刺激高潮av | 在线1区 | 日本成人二区 | 久久精品中文字幕一区 | 欧美电影在线观看 | 中文字幕 亚洲一区 | 97干色 | 久久久久久久久久91 | 毛片在线免费观看网址 | 高清国产福利 | 国产精品久久久久久久不卡 | 国产毛片自拍 | 成人午夜在线免费观看 | 国产一区二区视频在线播放 | va免费视频 | 国产一级二级视频 | 日本教室三级在线看 | 12av毛片| 免费人成在线播放 | 久久国产精品无码网站 | 色网在线视频 | 手机视频在线播放 | 看免费5xxaaa毛片 | 羞羞视频一区 | 538任你躁在线精品视频网站 | 久久精品国产99久久久古代 | 一级毛片免费版 | 免费久久久久 | 黄视频免费在线 | 国产精品福利一区 | 久久久www成人免费精品 | 91九色免费视频 | 天堂成人国产精品一区 | 久久精品一区二区三区四区五区 | h视频免费看 | 91嫩草丨国产丨精品入口 | 黄色av片在线观看 | 国产一区精品在线观看 |