先看代碼:
let fn1 = function (x) { return x + 10; }; let fn2 = function (x) { return x * 10; }; let fn3 = function (x) { return x / 10; };console.log(fn3(fn1(fn2(fn1(6)))));
這是幾個簡單的運算方法,但想輸出的是一個多層函式嵌套的運行結果,即把前一個函式的運行結果賦值給后一個函式,當然我們可以寫成一下這樣:
let x = fn1(6); x = fn2(x); x = fn1(x); x = fn3(x);
但現在我就想用一個函式解決這種問題,形如:
compose(fn1, fn2, fn1, fn3)(6);
這個compose函式就是這篇文章介紹的——函式呼叫的扁平化,即把層級嵌套的那種函式呼叫(一個函式的運行結果當作實參傳給下一個函式的這種操作)扁平化,這就是compose函式,
那么下面就是開始實作這個函式:
首先我們看引數,需要給出不確定個數的函式:
function compose(...funcs) { //=>funcs:傳遞的函式集合 }
compose函式執行后跟個(),說明函式執行完再執行一個函式,即函式執行完會回傳一個新函式,而且也會給出第一次呼叫函式時的引數:
function compose(...funcs) { //=>funcs:傳遞的函式集合 return function proxy(...args) { //=>args:第一次呼叫函式傳遞的引數集合 } }
繼續往下進行,我們需要判斷給出的函式集合的個數,如果沒有給函式,我們只需將后一個的引數回傳,如果只給出一個函式,我們只需把后一個的引數賦給這個函式去執行即可:
function compose(...funcs) { //=>funcs:傳遞的函式集合 return function proxy(...args) { //=>args:第一次呼叫函式傳遞的引數集合 let len = funcs.length; if (len === 0) { //=>一個函式都不需要執行,直接回傳ARGS return args; } if (len === 1) { //=>只需要執行一個函式,把函式執行,把其結果回傳即可 return funcs[0](...args); } }; }
如果給出的引數集合是兩個及以上,那就是把前一個函式的執行結果賦給后一個函式,說到這,應該會想到一個滿足這個需求的陣列方法——reduce:
function compose(...funcs) { //=>funcs:傳遞的函式集合 return function proxy(...args) { //=>args:第一次呼叫函式傳遞的引數集合 let len = funcs.length; if (len === 0) { //=>一個函式都不需要執行,直接回傳ARGS return args; } if (len === 1) { //=>只需要執行一個函式,把函式執行,把其結果回傳即可 return funcs[0](...args); } return funcs.reduce((x, y) => { }); }; }
但這里需要注意的是,第一次執行的時候,引數x是個函式,之后再執行的時候x是個函式執行的結果,所以需要進行判斷:
function compose(...funcs) { //=>funcs:傳遞的函式集合 return function proxy(...args) { //=>args:第一次呼叫函式傳遞的引數集合 let len = funcs.length; if (len === 0) { //=>一個函式都不需要執行,直接回傳ARGS return args; } if (len === 1) { //=>只需要執行一個函式,把函式執行,把其結果回傳即可 return funcs[0](...args); } return funcs.reduce((x, y) => { return typeof x === "function" ? y(x(...args)) : y(x) }); }; }
這樣,compose函式完成,
當然,redux原始碼中的compose.js也可以實作一開始想要的效果:
export default function compose(...funcs) { if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } return funcs.reduce((a, b) => (...args) => a(b(...args))) }
但它和我們寫的compose函式有些不同,它執行的順序是函式集合中的函式從后往前執行,所以結果也會不同:
compose(fn1, fn2, fn1, fn3)(6)); //=> 用第一個compose執行的結果是17,用redux的執行結果是116
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/148810.html
標籤:JavaScript
下一篇:JavaScript之BOM基礎
