一、基礎知識
函數柯里化(currying)是指把一個接受多個參數的函數轉化為接受一個單一參數(最初函數的第一個參數)的函數,並且返回接受餘下參數且返回結果的新函數的技術。如果該函數的所有參數都被提供,則直接返回運算結果。
下面是一個常規的函數式編程的例子:
function add(a, b, c) { return a + b + c; } let curry = fn => judge = (...args) => args.length === fn.length ? fn(...args) : (arg) => judge(...args, arg); let curriedAdd = curry(add); console.log(curriedAdd(1)(2)(3)); // 輸出6
上面的例子中,curry函數是一個判斷函數參數是否齊全的柯里化函數,curriedAdd為柯里化之後的函數,當函數參數齊全時,輸出函數結果。這是一個基礎的柯里化函數的寫法。
二、實現鏈式調用
在JavaScript中,函數的鏈式調用可以通過返回this
實現,例:
let obj = { a: 1, add(b) { this.a += b; return this; }, sub(b) { this.a -= b; return this; }, out() { console.log(this.a); } }; obj.add(2).sub(1).out(); // 輸出2
上面的例子中,add
和sub
函數都返回了this
,便可以進行鏈式調用。為了實現函數柯里化和鏈式調用,我們可以結合起來寫:
function add(a) { let fn = b => add(a + b); fn.valueOf = () => a; return fn; } console.log(add(1)) // 輸出 1 console.log(add(1)(2)) // 輸出 3 console.log(add(1)(2)(3)) // 輸出 6
上面例子中的add
函數處理了一個參數a,然後返回一個新的函數,新的函數也會處理一個參數b,並返回調用自己的新的函數。最終返回一個內置了一個valueOf
方法的函數,這個方法會返回一個數值。
為了實現鏈式調用,我們需要重寫這個valueOf
方法,使得當此函數最終返回時,返回的結果是想要的計算結果。
function add(a) { let fn = b => add(a + b); fn.valueOf = () => a; return fn; } function sub(a) { let fn = b => sub(a - b); fn.valueOf = () => a; return fn; } console.log(add(1)(2)(3) + sub(1)(2)(3)) // 輸出1
這個例子中,我們定義了一個add
函數和一個sub
函數,他們都返回一個處理函數。當我們使用valueOf
方法獲取該函數時,它們的返回值就是函數生成時的a
值,這樣就可以完成加減鏈式計算了。
三、實現複雜的鏈式調用
對於基於函數柯里化的鏈式調用,在代碼維護和重構時可能會出現困難。為了更好的可讀性和可維護性,我們可能需要用到一種更加靈活的方式實現鏈式調用。下面是一種將數組方法與函數柯里化結合的方式,實現鏈式調用的示例:
const add = x => y => x + y; const double = x => x * 2; const result = [1, 2, 3, 4, 5] .filter(n => n % 2) .map(add(1)) .map(double) .reduce(add(0))(); console.log(result); // 輸出25
這個例子中,我們將數組先進行filter
操作,過濾掉不符合要求的元素,接著進行map
操作將每個元素都傳入add
函數,添加1以後再傳入double
函數,最終使用reduce
函數對數組元素進行求和。在上述每個函數中,我們都使用了柯里化函數的形式,使得鏈式調用可以繼續下去。
四、小結
在本文中,我們簡單了解了函數柯里化的基本知識,和如何使用函數柯里化實現JavaScript函數鏈式調用。另外,我們還了解了使用數組方法和函數柯里化實現JavaScript函數鏈式調用的簡單示例。由於JavaScript的靈活性,我們可以根據不同的場景選擇不同的實現方式,提高代碼的可讀性和可維護性。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/190491.html