Javascript 高階函式

yuzhihui發表於2023-02-08

一、高階函式

JavaScript 中的高階函式是一種接受函式作為輸入或返回函式作為輸出的函式。它們提供了靈活的方式來處理函式,並允許把函式作為引數或返回值傳遞。它們是函式語言程式設計的重要組成部分,並且可以提高程式碼的可讀性和可維護性。

高階函式的一個常見用法是對陣列進行操作,例如使用 map()reduce()filter()。這些函式允許您在陣列上應用自定義的函式,並對陣列的每個元素執行操作。

另一個常見的高階函式是回撥函式。回撥函式是一種被傳遞到另一個函式中的函式,並在某些事件發生時被呼叫。它們允許您建立程式碼,該程式碼在事件發生時自動執行。

另外,高階函式還可以用於建立抽象概念,例如柯里化組合管道。柯里化是一種將多個引數的函式轉換為一系列接受單個引數的函式的技術。組合是將多個函式組合成一個新函式的技術。管道是一種透過將函式的輸出作為下一個函式的輸入來連結多個函式的技術。

高階函式也可以與閉包結合使用。閉包是一種函式,它引用了定義它的作用域之外的變數。這使得您可以在函式外訪問函式內部的變數,並將變數儲存在記憶體中以供以後使用。

高階函式是 JavaScript 程式設計的重要概念,具有很多用途,並且可以提高程式碼的複雜性。學習如何使用高階函式,並將其與其他技術結合起來,可以使您的程式碼更加強大和高效。

 

一個常見的 JavaScript 高階函式示例是 Array.prototype.map()

const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = numbers.map(function(number) {
  return number * 2;
});
console.log(doubledNumbers); // [2, 4, 6, 8, 10]

在這個例子中,我們建立了一個陣列,然後使用 map() 函式對陣列中的每個元素進行操作。我們傳遞了一個回撥函式,該回撥函式接受一個數字,並返回該數字的兩倍。

另一個常見的高階函式示例是 Array.prototype.reduce()

const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce(function(total, number) {
  return total + number;
}, 0);
console.log(sum); // 15

在這個例子中,我們使用 reduce() 函式對陣列中的所有元素進行操作。我們傳遞了一個回撥函式,該回撥函式接受當前的總和和數字,並返回新的總和。

這些示例說明瞭高階函式的強大功能,以及如何將其與其他技術(例如回撥函式)結合起來,以實現複雜的操作。

二、使用高階函式實現函式柯里化

柯里化是一種高階函式的技術,可以將多個引數的函式轉換為只有一個引數的函式。這可以使我們在需要的時候再傳遞其他引數,並逐步構建出完整的函式。

以下是 JavaScript 使用高階函式實現柯里化的示例:

function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(null, args);
    } else {
      return function(...args2) {
        return curried.apply(null, args.concat(args2));
      };
    }
  };
}

function add(a, b, c) {
  return a + b + c;
}

const curriedAdd = curry(add);
const add5 = curriedAdd(5);
console.log(add5(10, 15)); // 30

在這個例子中,我們建立了一個 curry() 函式,該函式接受一個函式作為引數,並返回一個新函式。該新函式使用 apply() 方法應用所有引數,如果傳遞的引數數量不夠,則返回一個新的函式,該函式將傳遞的引數與當前的引數合併。

然後,我們使用 curry() 函式對 add() 函式進行柯里化,並建立了一個只接受一個引數的函式,該引數為 5。我們可以使用此函式來逐步構建出完整的函式,並使用最後兩個引數計算結果。

三、使用高階函式實現組合函式

組合函式是一種將多個函式結合起來以建立新函式的技術。在 JavaScript 中,可以使用高階函式實現組合函式。

以下是使用高階函式實現組合函式的示例:

function compose(f, g) {
  return function(x) {
    return f(g(x));
  };
}

function double(x) {
  return x * 2;
}

function add(x) {
  return x + 1;
}

const composed = compose(add, double);
console.log(composed(3)); // 7

在這個例子中,我們建立了一個 compose() 函式,該函式接受任意數量的函式作為引數,並返回一個新函式。

然後,我們使用 compose() 函式將 double()add() 函式組合在一起,並使用組合函式對數字 3 進行計算。因此,先呼叫 double(3),再呼叫 add(6),最後得到結果 7。

 

以下是另一種使用高階函式實現組合函式的示例:

function compose(...fns) {
  return function(arg) {
    return fns.reduceRight((result, fn) => fn(result), arg);
  };
}

function double(x) {
  return x * 2;
}

function add(x) {
  return x + 1;
}

const composed = compose(double, add);
console.log(composed(3)); // 8

在這個例子中,我們建立了一個 compose() 函式,該函式接受任意數量的函式作為引數,並返回一個新函式。該新函式使用 reduceRight() 函式對所有函式進行組合,並對給定的引數進行計算。

然後,我們使用 compose() 函式將 double()add() 函式組合在一起,並使用組合函式對數字 3 進行計算。因此,先呼叫 add(3),再呼叫 double(4),最後得到結果 8。

四、使用高階函式實現管道

 管道是一種將多個函式連線起來以進行順序計算的技術。在 JavaScript 中,可以使用高階函式實現管道。

以下是使用高階函式實現管道的示例:

function pipe(...fns) {
  return function(arg) {
    return fns.reduce((result, fn) => fn(result), arg);
  };
}

function double(x) {
  return x * 2;
}

function add(x) {
  return x + 1;
}

const piped = pipe(add, double);
console.log(piped(3)); // 8

在這個例子中,我們建立了一個 pipe() 函式,該函式接受任意數量的函式作為引數,並返回一個新函式。該新函式使用 reduce() 函式對所有函式進行管道,並對給定的引數進行計算。

然後,我們使用 pipe() 函式將 add()double() 函式管道在一起,並使用管道函式對數字 3 進行計算。因此,先呼叫 add(3),再呼叫 double(4),最後得到結果 8。

五、組合函式和管道的區別

管道和組合函式都是高階函式的應用,但是它們有著明顯的不同:

  1. 實現方式:管道是透過將多個函式連線起來,依次對資料進行處理,而組合函式則是透過將多個函式組合成一個函式。

  2. 計算順序:管道函式的計算順序是從左到右而組合函式的計算順序是從右到左

  3. 結構:管道函式的結構是一維的,每一步的結果都是下一步的輸入;而組合函式的結構是二維的,一個函式的結果可以作為另一個函式的輸入。

因此,管道和組合函式都是高階函式的重要應用,在不同的場景中使用它們都有著獨特的優勢。

 

相關文章