1. 函數柯里化一般是指把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的而且返回一個接受餘下的參數並且返回結果的新函數的技術。javascript
// 1. 最簡單的柯里化 // sum函數接受三個參數,並返回求和結果 var sum = function(a,b,c) { return a+b+c; } // 最簡單柯里化的sum函數 var sum_curry = function(a){ return function(b,c){ return a+b+c; } }
2. 更泛化的定義是指給函數分步傳遞參數,每次函數接受部分參數後應用這些參數,並返回一個函數接受剩下的參數,這中間可嵌套多層這樣的接受部分參數的函數,直至返回最後結果。概括一下就是逐步傳參,逐步縮小函數的適用範圍,逐步求解的過程。java
// 2. 泛化的柯里化 // currying實現將一個函數轉變爲柯里化函數 var currying = function (fn) { var _args = []; return function () { if (arguments.length === 0) { // 實現最終的計算 return fn.apply(this, _args); } // 這裏只是簡單的將參數緩存起來(用於解釋柯里化概念,並不是實際應用場景) Array.prototype.push.apply(_args, [].slice.call(arguments)); return arguments.callee; } }; // sum函數接受任意參數,並返回求和結果 var sum=function () { var total = 0; for (var i = 0, c; c = arguments[i++];) { total += c; } return total; }; // 或得一個泛化柯里化的sum函數 var sum_curry = currying(sum); sum_curry(1)(2,3); sum_curry(4); console.log(sum_curry());
3. 從更上層的角度去理解,柯里化容許和鼓勵你將一個複雜過程分割成一個個更小的更容易分析的過程(這些小的邏輯單元將更容易被理解和測試),最後這樣一個難於理解複雜的過程將變成一個個小的邏輯簡單的過程的組合。ajax
// 3.上面兩個例子很好的解釋了什麼是函數柯里化,可是何時用?任何能簡化邏輯實現、提升可讀性地方都鼓勵使用,舉個稍微具體點的列子: // refresh函數實現經過ajax請求更新頁面上的相關模塊的數據。 function refresh(url, callback){ // ajax_get實現一個ajax get請求,請求成功後回調callback函數。 ajax_get(url, callback); } function update(data){ // 更新的邏輯所有在這裏處理 } refresh("xxx?target=news", update); // update函數是一個柯里化後函數,第一級函數根據傳入參數將須要更新的模塊分拆出來。 function update(target){ var _elm = document.getElementById(target); // 這裏實現模塊分拆,代碼僅是舉例 return function(data){ // 返回一個用請求結果更新頁面顯示的函數 _elm.innerHTML = data; // 這裏實現用ajax請求返回結果更新頁面顯示過程,代碼僅是舉例 } } // 更新頁面能夠寫成這樣 refresh("xxx?target=news", update("news")); refresh("xxx?target=pictures", update("pictures")); // 繼續,若是新聞模塊須要繼續拆分紅「社會」新聞,「娛樂」新聞,那咱們柯里化的update函數該怎麼寫呢?能夠這樣寫: function update(target){ var _elm = document.getElementById(target); // 這裏實現第一級模塊分拆,代碼僅是舉例 return function(type){ // 返回一個接受其他參數的函數 var _elm = document.getElementById(item); // 這裏實現第二級模塊分拆,代碼僅是舉例 return function(data){ // 返回一個接受其他參數並最終更新頁面顯示的函數 _elm.data = data; // 這裏實現用ajax請求返回結果更新頁面顯示過程,代碼僅是舉例 } } } // 更新頁面就能夠寫成這樣 refresh("action.do?target=news&type=society", update("news")("society")); refresh("action.do?target=news&type=entertainment", update("news")("entertainment"));