亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > 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);  }};

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲自拍偷拍色片视频| 精品在线欧美视频| 久久久久久亚洲| 亚洲成色999久久网站| 韩国19禁主播vip福利视频| 在线观看精品自拍私拍| 国内精品久久久久久久| 国产成人免费av| 伊人av综合网| 久久久久久久久久av| 国产精品jvid在线观看蜜臀| 欧美日韩亚洲一区二区| 91精品一区二区| 日韩理论片久久| 欧美在线精品免播放器视频| 国产精品一香蕉国产线看观看| 欧美电影免费观看高清完整| 麻豆一区二区在线观看| 国产精品视频一区二区高潮| 久久精品99国产精品酒店日本| 97久久久久久| 九九精品视频在线观看| 中文日韩电影网站| 成人写真福利网| 国产精品盗摄久久久| 色婷婷久久一区二区| 九九九久久久久久| 亚洲va欧美va国产综合久久| 欧美午夜宅男影院在线观看| 高跟丝袜一区二区三区| 欧美激情欧美狂野欧美精品| 伊人亚洲福利一区二区三区| 中文字幕综合一区| 亚洲欧美日韩国产中文专区| 日韩在线精品视频| 国内精品久久久久久久| 91在线中文字幕| 激情懂色av一区av二区av| 久久人人爽人人爽人人片亚洲| 国色天香2019中文字幕在线观看| 成人福利视频网| 欧美日韩国产精品一区二区不卡中文| 国产精品美女无圣光视频| 国产精品美乳一区二区免费| 91社区国产高清| 日本精品一区二区三区在线播放视频| 亚洲成人精品视频| 欧美午夜性色大片在线观看| 国内精品400部情侣激情| 国产精品一区二区三| 欧美黑人性视频| 精品国产一区二区三区在线观看| 日韩在线观看免费高清| 亚洲一区二区久久久久久久| 欧美丰满老妇厨房牲生活| 欧美美女操人视频| 在线观看欧美成人| 日韩av电影在线播放| 亚洲大尺度美女在线| 97人洗澡人人免费公开视频碰碰碰| 久久久久这里只有精品| 欧美一区二区影院| 热久久视久久精品18亚洲精品| 疯狂欧美牲乱大交777| 97热精品视频官网| 久久人人97超碰精品888| 日韩久久精品成人| 亚洲精品自拍偷拍| 久久久在线视频| 91av在线免费观看| 欧美性猛交xxxx富婆| 国产精品视频999| 91精品国产自产在线老师啪| 国产在线拍偷自揄拍精品| 亚洲va欧美va在线观看| 在线观看久久av| 久久中文字幕国产| 国产色综合天天综合网| 久久天天躁狠狠躁夜夜躁| 精品国产乱码久久久久酒店| 欧美日韩一区二区三区在线免费观看| 国产亚洲欧洲高清| 欧美色欧美亚洲高清在线视频| 亚洲国产成人爱av在线播放| 欧美日韩国产成人高清视频| 亚洲免费视频观看| 欧美成人午夜免费视在线看片| 亚洲精品中文字幕有码专区| 九九九久久国产免费| 亚洲精品日韩av| 国产激情久久久久| 色播久久人人爽人人爽人人片视av| 91在线高清免费观看| 欧美激情精品久久久久久免费印度| 亚洲精品456在线播放狼人| 日韩欧美一区二区三区| 亚洲精品一区中文| 国产在线视频不卡| 精品国产91久久久久久| 久久久免费精品视频| 成人精品久久av网站| 日韩在线视频免费观看高清中文| 精品亚洲一区二区三区| 欧美亚洲国产日韩2020| 日韩欧美一区视频| 亚洲国产99精品国自产| 亚洲人永久免费| 日韩国产精品亚洲а∨天堂免| 亚洲福利在线播放| 亚洲最新视频在线| 亚洲毛片一区二区| 成人妇女淫片aaaa视频| 91沈先生作品| 日韩欧美一区二区三区久久| 欧美国产第一页| 国产精品久久色| 91精品综合久久久久久五月天| 国产成人精品免高潮费视频| 国产精品欧美亚洲777777| 久久国产精品首页| 不卡中文字幕av| 97在线观看视频国产| 免费成人高清视频| 久久精品国产精品亚洲| 国产精品爽爽ⅴa在线观看| 国产精品扒开腿做爽爽爽的视频| 成人免费视频在线观看超级碰| 日韩中文字幕在线免费观看| 久久伊人精品一区二区三区| 日韩av不卡电影| 成人激情在线播放| 亚洲精品自拍偷拍| 亚洲韩国欧洲国产日产av| 国产精品视频久久| 国产精品视频一区二区三区四| 成人网中文字幕| 久久99国产精品久久久久久久久| 精品国产老师黑色丝袜高跟鞋| 久久综合国产精品台湾中文娱乐网| 欧美一级大胆视频| 在线观看日韩av| 精品国产依人香蕉在线精品| 亚洲视频在线观看免费| 中文字幕日韩精品有码视频| 亚洲香蕉成人av网站在线观看| 国产精品久久77777| 伊人伊成久久人综合网小说| 亚洲精品av在线播放| 色偷偷亚洲男人天堂| 国产精品爽爽爽爽爽爽在线观看| 亚洲韩国欧洲国产日产av| 久久99视频精品| 国产成人精品视频在线| 欧美激情免费视频| 日韩电影大全免费观看2023年上| 欧美日韩国产区| 亚洲欧美日韩视频一区| 久久精品亚洲94久久精品| 日韩av在线导航| 亚洲欧洲国产一区| 欧美精品在线观看| 欧美裸体xxxx极品少妇软件| 国产精品九九九| 尤物精品国产第一福利三区|