摘要:作為函數式編程語言,帶來了很多語言上的有趣特性,比如柯里化和反柯里化。而反柯里化,從字面講,意義和用法跟函數柯里化相比正好相反,擴大適用范圍,創建一個應用范圍更廣的函數。
作為函數式編程語言,JS帶來了很多語言上的有趣特性,比如柯里化和反柯里化。
可以對照另外一篇介紹 JS 柯里化 的文章一起看~
1. 簡介柯里化,是固定部分參數,返回一個接受剩余參數的函數,也稱為部分計算函數,目的是為了縮小適用范圍,創建一個針對性更強的函數。核心思想是把多參數傳入的函數拆成單參數(或部分)函數,內部再返回調用下一個單參數(或部分)函數,依次處理剩余的參數。
而反柯里化,從字面講,意義和用法跟函數柯里化相比正好相反,擴大適用范圍,創建一個應用范圍更廣的函數。使本來只有特定對象才適用的方法,擴展到更多的對象。
2. 實現先來看看反柯里化的通用實現吧~
Function.prototype.unCurrying = function() { const self = this return function(...rest) { return Function.prototype.call.apply(self, rest) } }解釋下:
為Function原型添加uncurrying方法,并在執行的時候保存執行unCurrying的方法到self
借用apply把要借用的函數作為this環境賦給call,并傳入之后的形參作為參數執行
還有一個實現:
Function.prototype.unCurrying = function() { return this.call.bind(this) }如果你覺得把函數放在Function.prototype上不太好,也可以這樣:
function unCurrying(fn) { return function(tar, ...argu) { return fn.apply(tar, argu) } } 3. 使用 3.1 簡單使用用unCurrying通用實現簡單的實用一下試試:
Function.prototype.unCurrying = function() { const self = this // 這里的self就是Array.prototype.push方法 return function(...rest) { // rest為傳入的兩層參數[[1,2,3],4] return Function.prototype.call.apply(self, rest) } } const push = Array.prototype.push.unCurrying() ~function(...rest) { // rest:[1,2,3] push(rest, 4) console.log(rest) // [1, 2, 3, 4] }(1, 2, 3) 3.2 借用其他方法反柯里化其實反映的是一種思想,即擴大方法的適用范圍,仍然調用剛剛的通用unCurrying方法借用push方法:
const push = Array.prototype.push.unCurrying() const obj = { a: "嘻嘻" } push(obj, "呵呵", "哈哈", "嘿嘿") console.log(obj) // { "0": "呵呵", "1": "哈哈", "2": "嘿嘿", a: "嘻嘻", length: 3 }相當于obj.push(...),obj不僅多了類似于數組一樣以數字作為索引的屬性,還多了個類似于數組的length屬性,讓引擎自動管理數組成員和length屬性;(文后有V8引擎實現push方法的源碼) 這樣一個數組的push方法就被借用出來,可以應用于任何其他對象了。
只要是方法,unCurrying就可以借用,call方法也可以:
var call = Function.prototype.call.unCurrying(); function $(id) { return this.getElementById(id); } call($, document, "demo") // #demo 元素相當于document.$("demo"),成功的借用了call方法,當然可以把document改成你希望作為this綁定到$的任何對象,比如{ getElementById:T=>console.log(T+"呃") } // demo呃
3.3 借用自己unCurrying本身也是方法,也可以借用自己...-。-
const unCurrying = Function.prototype.unCurrying.unCurrying() const map = unCurrying(Array.prototype.map) map({ 0: 4, 1: "a", 2: null, length: 3 }, n => n + n) // [8, "aa", 0]神奇吧~
4. 總結簡單說,函數柯里化就是對高階函數的降階處理,縮小適用范圍,創建一個針對性更強的函數。舉栗子:
function(arg1,arg2) // => function(arg1)(arg2) function(arg1,arg2,arg3) // => function(arg1)(arg2)(arg3) function(arg1,arg2,arg3,arg4) // => function(arg1)(arg2)(arg3)(arg4) function(arg1,arg2,…,argn) // => function(arg1)(arg2)…(argn)而反柯里化就是反過來,增加適用范圍,讓方法使用場景更大。使用unCurrying, 可以把原生方法借出來,讓任何對象擁有原生對象的方法。舉個栗子:
obj.func(arg1, arg2) // => func(obj, arg1, arg2)也可以這樣理解: 柯里化是在運算前提前傳參,可以傳遞多個參數; 反柯里化是延遲傳參,在運算時把原來已經固定的參數或者this上下文等當作參數延遲到未來傳遞。
附:
V8引擎中Array.prototype.push方法源碼實現:
function ArrayPush() { var n = TO_UINT32(this.length); var m = %_ArgumentsLength(); for (var i = 0; i < m; i++) { this[i + n] = %_Arguments(i); // 屬性拷貝 this.length = n + m; // 修正length return this.length; } }網上的帖子大多深淺不一,甚至有些前后矛盾,在下的文章都是學習過程中的總結,如果發現錯誤,歡迎留言指出~
參考:
JS 柯里化
前端開發者進階之函數反柯里化unCurrying
JavaScript中有趣的反柯里化
js柯里化適用場景,優缺點分別是什么,還有個反柯里化?
JS進階篇--JS中的反柯里化( uncurrying)
PS:歡迎大家關注我的公眾號【前端下午茶】,一起加油吧~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/6745.html
摘要:柯里化通用式上面的柯里化函數沒涉及到高階函數,也不具備通用性,無法轉換形參個數任意或未知的函數,我們接下來封裝一個通用的柯里化轉換函數,可以將任意函數轉換成柯里化。 showImg(https://segmentfault.com/img/remote/1460000018998373); 閱讀原文 前言 在 JavaScript 中,柯里化和反柯里化是高階函數的一種應用,在這之前...
摘要:作為函數式編程語言,帶來了很多語言上的有趣特性,比如柯里化和反柯里化。在一些函數式編程語言中,會定義一個特殊的占位變量。個人理解不知道對不對延遲執行柯里化的另一個應用場景是延遲執行。不斷的柯里化,累積傳入的參數,最后執行。作為函數式編程語言,JS帶來了很多語言上的有趣特性,比如柯里化和反柯里化。 這里可以對照另外一篇介紹 JS 反柯里化 的文章一起看~ 1. 簡介 柯里化(Currying)...
摘要:最后,我們反過來看,其實反柯里化相當于把原來的形式,轉換成了,使得的使用范圍泛化了。更抽象地表達,反柯里化,使得原來調用,可以轉成形式的調用。 反柯里化 相反,反柯里化的作用在與擴大函數的適用性,使本來作為特定對象所擁有的功能的函數可以被任意對象所用.即把如下給定的函數簽名, obj.func(arg1, arg2) 轉化成一個函數形式,簽名如下: func(obj, arg1, ar...
摘要:但是,對函數式編程而言,這個行為的重要性是毋庸置疑的。關于該模式更正式的說法是偏函數嚴格來講是一個減少函數參數個數的過程這里的參數個數指的是希望傳入的形參的數量。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關于譯者:這是一個流淌著滬江血液的純粹工程:認真,是 HTML 最堅實的梁柱;分享,是...
摘要:作為函數式編程語言,帶來了很多語言上的有趣特性,比如柯里化和反柯里化。個人理解不知道對不對延遲執行柯里化的另一個應用場景是延遲執行。不斷的柯里化,累積傳入的參數,最后執行。 作為函數式編程語言,JS帶來了很多語言上的有趣特性,比如柯里化和反柯里化。 這里可以對照另外一篇介紹 JS 反柯里化 的文章一起看~ 1. 簡介 柯里化(Currying),又稱部分求值(Partial Evalu...
閱讀 3199·2021-11-10 11:36
閱讀 3145·2021-11-02 14:39
閱讀 1726·2021-09-26 10:11
閱讀 4929·2021-09-22 15:57
閱讀 1685·2021-09-09 11:36
閱讀 2053·2019-08-30 12:56
閱讀 3487·2019-08-30 11:17
閱讀 1702·2019-08-29 17:17