摘要:三使用場景場景性能優化可以將一些模板代碼通過柯里化的形式預先定義好,例如這段代碼的作用就是根據瀏覽器的類型決定事件添加的方式。場景擴展能力中的方法,就是通過柯里化實現的四總結通過本文的介紹,相信你對柯里化已經有一個全新的認識了。
歡迎關注我的公眾號睿Talk,獲取我最新的文章:
柯里化,是函數式編程的一個重要概念。對于沒接觸過的人來說,會被一串串的小括號弄得摸不著頭腦。但一旦理解了其中的含義和具體的使用場景,你一定會對它愛不釋手。它既能減少代碼冗余,也能增加可讀性,可謂程序猿居家旅行,裝逼撕逼必備之良藥。
二、什么是柯里化如果一個函數可以接收多個參數,將這個函數轉化為每次只接收一部分參數的函數的多次調用形式,就是柯里化。文字上理解比較困難,先來看看下面的代碼:
function add(a, b, c) { return a + b + c; }
這個add函數接收3個參數,返回3個參數相加的結果。可以通過以下2種形式對其進行柯里化:
function addOne(a) { return function(b) { return function(c) { return a + b + c; } } } } function addTwo(a,b) { return function(c) { return a + b + c; } }
執行的時候,以下3種方式都會獲得一樣的結果:
add(1, 2, 3); // return 6 addOne(1)(2)(3); // return 6 addTwo(1, 2)(3); // return 6
如果使用ES6語法,能更簡潔的寫出柯里化后的函數,以addOne為例:
const addOne = (a) => (b) => (c) => (a + b + c)
上面的例子沒有什么實際的意義,只是為了說明概念而已。在了解基本概念后,我們來聊聊實際的使用場景。
三、使用場景場景1: 性能優化
可以將一些模板代碼通過柯里化的形式預先定義好,例如:
var addEvent = function(el, type, fn, capture) { if (window.addEventListener) { el.addEventListener(type, function(e) { fn.call(el, e); }, capture); } else if (window.attachEvent) { el.attachEvent("on" + type, function(e) { fn.call(el, e); }); } }; addEvent(element, "click", handleClick, true);
這段代碼的作用就是根據瀏覽器的類型決定事件添加的方式。實際上if...else的判斷只需要進行一次。將它柯里化后可以得到以下結果:
function addCrossBrowserEvent() { if (window.addEventListener) { return function(el, sType, fn, capture) { el.addEventListener(sType, function(e) { fn.call(el, e); }, (capture)); }; } else if (window.attachEvent) { return function(el, sType, fn, capture) { el.attachEvent("on" + sType, function(e) { fn.call(el, e); }); }; } } var addEvent = addCrossBrowserEvent(); addEvent(element, "click", handleClick, true);
場景2: 代碼復用
在有回調函數的場景下,可以通過柯里化傳入一些預設的值,排列組合后,達到代碼復用的效果:
// 匹配任何正則的函數 const match = (reg) => (str) => str.match(reg); // 專門匹配空格 const hasSpace = match(/s+/g); // 封裝數組的 filter 方法 const filter = (fn) => (arr) => arr.filter(fn); // 專門找空格的 filter 方法 const findSpace = filter(hasSpace); // 使用 let result = findSpace(["hi man", "hi_man"]); //["hi man"]
使用傳統的方法實現以上效果,如下:
let result = ["hi man", "hi_man"].filter( (item) => (item.match(/s+/g)) );
雖然傳統的方法看起來代碼量比較少,但如果在很多地方需要使用的時候,就體現出封裝的威力了。而且,還可以為filter方法傳入其它的條件生成各式各樣的find工具函數!
場景3: 使代碼便于理解
react-redux的connect方法,就是使用了柯里化增加代碼的可讀性:
let Container = connect(mapStateToProps, mapDispatchToProps)(Component);
在這里,connect的作用就是將Component要用到的state切面和action注入到它的property中,達到展示型組件和容器組件分離的目的。如果將這個方法的定義改為:
let Container = connect(mapStateToProps, mapDispatchToProps, Component);
就沒那么好理解了。而且,mapStateToProps和mapDispatchToProps實際上也是可選參數,在不傳它們的情況下傳入Component會顯得很惡心: connect(null, null, Component)。
場景4: 擴展Javascript能力
ES5中的bind方法,就是通過柯里化實現的:
if (!Function.prototype.bind) { Function.prototype.bind = function(oThis) { if (typeof this !== "function") { throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function() {}, fBound = function() { return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); }; if (this.prototype) { fNOP.prototype = this.prototype; } fBound.prototype = new fNOP(); return fBound; }; }四、總結
通過本文的介紹,相信你對柯里化已經有一個全新的認識了。它最少有以下4種功能:
性能優化
代碼復用
使代碼便于理解
擴展Javascript能力
靈活使用柯里化,提高代碼質量不是夢!
P.S. 如果還有本文沒有提到的柯里化用法,歡迎留言交流(^-^)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/84963.html
摘要:原文鏈接和都支持函數的柯里化函數的柯里化還與的函數編程有很大的聯系如果你感興趣的話可以在這些方面多下功夫了解相信收獲一定很多看本篇文章需要知道的一些知識點函數部分的閉包高階函數不完全函數文章后面有對這些知識的簡單解釋大家可以看看什么是柯里化 原文鏈接 Haskell和scala都支持函數的柯里化,JavaScript函數的柯里化還與JavaScript的函數編程有很大的聯系,如果你感興...
摘要:作為函數式編程語言,帶來了很多語言上的有趣特性,比如柯里化和反柯里化。在一些函數式編程語言中,會定義一個特殊的占位變量。個人理解不知道對不對延遲執行柯里化的另一個應用場景是延遲執行。不斷的柯里化,累積傳入的參數,最后執行。作為函數式編程語言,JS帶來了很多語言上的有趣特性,比如柯里化和反柯里化。 這里可以對照另外一篇介紹 JS 反柯里化 的文章一起看~ 1. 簡介 柯里化(Currying)...
摘要:作為函數式編程語言,帶來了很多語言上的有趣特性,比如柯里化和反柯里化。而反柯里化,從字面講,意義和用法跟函數柯里化相比正好相反,擴大適用范圍,創建一個應用范圍更廣的函數。作為函數式編程語言,JS帶來了很多語言上的有趣特性,比如柯里化和反柯里化。 可以對照另外一篇介紹 JS 柯里化 的文章一起看~ 1. 簡介 柯里化,是固定部分參數,返回一個接受剩余參數的函數,也稱為部分計算函數,目的是為了縮...
摘要:作為函數式編程語言,帶來了很多語言上的有趣特性,比如柯里化和反柯里化。個人理解不知道對不對延遲執行柯里化的另一個應用場景是延遲執行。不斷的柯里化,累積傳入的參數,最后執行。 作為函數式編程語言,JS帶來了很多語言上的有趣特性,比如柯里化和反柯里化。 這里可以對照另外一篇介紹 JS 反柯里化 的文章一起看~ 1. 簡介 柯里化(Currying),又稱部分求值(Partial Evalu...
摘要:柯里化通用式上面的柯里化函數沒涉及到高階函數,也不具備通用性,無法轉換形參個數任意或未知的函數,我們接下來封裝一個通用的柯里化轉換函數,可以將任意函數轉換成柯里化。 showImg(https://segmentfault.com/img/remote/1460000018998373); 閱讀原文 前言 在 JavaScript 中,柯里化和反柯里化是高階函數的一種應用,在這之前...
閱讀 3172·2021-11-19 09:40
閱讀 3663·2021-11-16 11:52
閱讀 2991·2021-11-11 16:55
閱讀 3189·2019-08-30 15:55
閱讀 1192·2019-08-30 13:08
閱讀 1666·2019-08-29 17:03
閱讀 3022·2019-08-29 16:19
閱讀 2588·2019-08-29 13:43