JavaScript函式柯里化詳解
本章節詳細介紹一下如何實現函式柯里化,需要的朋友可以做一下參考。
關於函式柯里化的作用可以參閱JavaScript函式柯里化的作用一章節。
百科上關於函式柯里化的定義如下:
[HTML] 純文字檢視 複製程式碼在電腦科學中,柯里化(Currying)是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,並且返回接受餘下的引數且返回結果的新函式的技術。
上面的概念雖然已經闡明柯里化的概念,但是對於初學者來說可能會有一點困擾,下面就通過程式碼例項介紹一下什麼是函式的柯里化,並且它是如何實現的。函式柯里化的呼叫外在表現如下:
[JavaScript] 純文字檢視 複製程式碼add(1)(2)(3)(4)
原本的呼叫方式如下:
[JavaScript] 純文字檢視 複製程式碼add(1,2,3,4)
通過上面的兩段程式碼,是不是可以對函式柯里化的理解增加了一點。
看下面一個最為原始的實現方式:
[JavaScript] 純文字檢視 複製程式碼var uncurried = function (a, b, c) { //code }; var curried = function (a) { return function (b) { return function (c) { //code }; }; };
第二個函式就是最為粗野的一種柯里化實現方式,如果巢狀的函式很多的話,那複雜程度是無法想象的。
下面就介紹一下如何實現一個通用的柯里化函式,先看一個程式碼例項:
[JavaScript] 純文字檢視 複製程式碼function sub_curry(fn /*, 其他引數 */) { var args = [].slice.call(arguments, 1); return function () { return fn.apply(this, args.concat(toArray(arguments))); }; }
下面簡單對上面的程式碼做一下介紹:
(1).fn是要被柯里化的函式。
(2)./*, 其他引數 */,要被傳遞的引數,比如fn(a,b,c),這個引數可以是"a,b,c"或者"a,b"等。
(3).var args = [].slice.call(arguments, 1),這個是將sub_curry的除去fn外的引數轉換為一個陣列。
(4).return function () {
return fn.apply(this, args.concat(toArray(arguments)));
},返回一個函式,此函式可以接受新的引數,這些新引數可以和args合併,也就是應該傳遞給fn的引數。
使用方式如下:
[JavaScript] 純文字檢視 複製程式碼var fn = function (a, b, c) { return [a, b, c]; }; fn("a", "b", "c"); sub_curry(fn, "a")("b", "c"); sub_curry(fn, "a", "b")("c"); sub_curry(fn, "a", "b", "c")();
上面程式碼的幾種使用方式都是等價的,已經很有函式柯里化的感覺了(在很多教程中函式柯里化就到此為止),但是還是不夠完美,因為上面的方式只有()()這麼兩級呼叫,再多就不好用了,下面就給出一個比較完美的函式柯里化程式碼:
[JavaScript] 純文字檢視 複製程式碼執行程式碼function toArray(elements) { var core_slice = Array.prototype.slice; return core_slice.call(elements); } function sub_curry(fn /*, 其他引數 */) { var args = [].slice.call(arguments, 1); return function () { return fn.apply(this, args.concat(toArray(arguments))); }; } function curry(fn, length) { length = length || fn.length; return function () { if (arguments.length < length) { var combined = [fn].concat(toArray(arguments)); return curry(sub_curry.apply(this, combined), length - arguments.length); } else { return fn.apply(this, arguments); } }; } function func(a, b, c) { var num; num = a + b + c; return num; } var curriedFunc = curry(func); console.log(func(1,2,3)); console.log(curriedFunc(1)(2)(3));
上面的程式碼比較完美的實現了函式柯里化功能,下面介紹一下它的實現過程。
一.程式碼註釋:
(1).function toArray(elements) {},此函式可以將集合轉換為陣列。
(2).var core_slice = Array.prototype.slice,將Array圓形物件中的slice方法的引用賦值給變數core_slice
(3).return core_slice.call(elements),將集合轉換為陣列,並返回。
(4).function sub_curry(){},此函式在上面已經介紹了,這裡就不做說明。
(5).function curry(fn, length) {},此函式實現了函式柯里化功能,第一個引數是要被柯里化的函式,第二個引數規定要傳遞幾次引數,也就是(para)的個數,比如如果length是2,那麼舉要func(1)(2)這樣呼叫兩次,可以人為傳遞也可以通過fn.length獲取函式形參的數目,當然看具體的使用場景。
總體來說,curry()函式就是返回一個新的函式,此新函式能夠在傳遞的引數沒有達到length規定的個數時,繼續遞迴呼叫curry()函式,並且返回的所有新函式的引數最終能夠累積連線起來,最後傳遞給fn函式。
(6).length = length || fn.length,如果傳遞了length,就是用length,否則獲取fn函式的形參。
(7).return function () {},返回柯里化後的函式,可以遞迴呼叫curry()函式,用來實現引數的累積。
(8).if (arguments.length < length) {},判斷傳遞的引數是否小於length,如果不小於的話,那麼說明已經是最後一個()呼叫了,那麼就執行return fn.apply(this, arguments),否則的話,就需要遞迴柯里化,繼續累積引數。
(9).var combined = [fn].concat(toArray(arguments)),將函式fn和傳遞的引數生成一個陣列。
(10).return curry(sub_curry.apply(this, combined), length - arguments.length),進行遞迴柯里化操作。
二.相關閱讀:
(1).slice()可以參閱javascript Array slice()一章節。
(2).prototype可以參閱javascript prototype原型一章節。
(3).apply()可以參閱javascript apply()一章節。
(4).concat()可以參閱javascript Array concat()一章節。
(5).arguments可以參閱javascript arguments一章節。
相關文章
- JavaScript函式柯里化JavaScript函式
- JavaScript函式柯里化的作用JavaScript函式
- Javascript currying柯里化詳解JavaScript
- [譯] JavaScript中的函式柯里化JavaScript函式
- JavaScript進階之函式柯里化JavaScript函式
- 函式柯里化函式
- JS:函式柯里化JS函式
- Js函式柯里化JS函式
- 深入理解javascript系列(十七):函式柯里化JavaScript函式
- 前端戰五渣學JavaScript——函式柯里化前端JavaScript函式
- 高階函式應用 —— 柯里化與反柯里化函式
- JS高階函式-函式柯里化JS函式
- JavaScript柯里化JavaScript
- 函式的合成與柯里化函式
- 前端之函式柯里化Currying前端函式
- 函式柯里化和偏函式應用函式
- 瞭解 JavaScript 函數語言程式設計 - 柯里化JavaScript函數程式設計
- [譯] 柯里化與函式組合函式
- JS 分步實現柯里化函式JS函式
- JS專題之函式柯里化JS函式
- js柯里化函式的好處JS函式
- javascript中bind繫結接收者與函式柯里化JavaScript函式
- JavaScript中的事件迴圈機制跟函式柯里化JavaScript事件函式
- JavaScript函數語言程式設計(純函式、柯里化以及組合函式)JavaScript函數程式設計函式
- JavaScript 函數語言程式設計---柯里化JavaScript函數程式設計
- 用大白話介紹柯里化函式函式
- JS中的 偏函式 和 柯里化JS函式
- JavaScript 中的函數語言程式設計:函式,組合和柯里化JavaScript函數程式設計函式
- 大佬,JavaScript 柯里化,瞭解一下?JavaScript
- 柯里化與反柯里化
- 「譯」理解JavaScript的柯里化JavaScript
- 「前端進階」徹底弄懂函式柯里化前端函式
- 手寫系列:call、apply、bind、函式柯里化APP函式
- JavaScript 函數語言程式設計技巧 - 反柯里化JavaScript函數程式設計
- 一段柯里化函式程式碼閱讀函式
- 深入 call、apply、bind、箭頭函式以及柯里化APP函式
- 【譯】理解JavaScript中的柯里化JavaScript
- 從 ES6 高階箭頭函式理解函式柯里化函式