8個JavaScript中高階函數的運用分享

函數作為參數傳遞

高階函數可以接受一個或多個函數作為參數,這些函數可以在高階函數中被調用,實現某種特定的功能

function operation(num1, num2, callback) {
    let result = callback(num1, num2);
    console.log(result);
}

function add(num1, num2) {
    return num1 + num2;
}

operation(2, 3, add); // 輸出 5

在上面的例子中,operation 函數接受三個參數,其中第三個參數是一個回調函數 callback,它的作用是對前兩個參數進行某種操作,返回操作結果。在調用 operation 函數時,我們將 add 函數作為 callback 參數傳入,從而實現瞭兩個數的加法運算

函數作為返回值

高階函數可以返回一個或多個函數,這些函數可以在其他地方調用,實現某種特定的功能

function multiplyBy(num) {
    return function(x) {
        return x * num;
    }
}

let multiplyBy2 = multiplyBy(2);
console.log(multiplyBy2(5)); // 輸出 10

在上面的例子中,multiplyBy 函數返回瞭一個匿名函數,該函數接受一個參數 x,並將其乘以 num 參數。我們將 multiplyBy(2) 賦值給 multiplyBy2 變量,從而得到一個新的函數,該函數可以將其參數乘以 2。最後,我們調用 multiplyBy2(5) ,得到 10

函數柯裡化

柯裡化是一個將多個參數的函數轉換為一系列單參數函數的過程。這種方式可以更方便地傳遞參數,提高代碼的可讀性和可維護性

function add(num1) {
    return function(num2) {
        return num1 + num2;
    }
}

let add5 = add(5);
console.log(add5(3)); // 輸出 8

在上面的例子中,add 函數接受一個參數 num1,並返回一個匿名函數,該函數接受一個參數 num2,並將其與 num1 相加。我們將 add(5) 賦值給 add5 變量,從而得到一個新的函數,該函數可以將其參數與 5 相加。最後,我們調用 add5(3) ,得到 8

函數組合

函數組合是將多個函數組合成一個新函數的過程。這種方式可以將多個操作封裝在一起,減少代碼的冗餘和重復

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

function multiplyBy2(num) {
    return num * 2;
}

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

let addThenMultiply = compose(multiplyBy2, add);
console.log(addThenMultiply(2)); // 輸出 6

在上面的例子中,我們定義瞭三個函數 addmultiplyBy2composeaddmultiplyBy2 分別實現瞭加 1 和乘以 2 的操作,compose 函數接受兩個函數作為參數,並返回一個新的函數,該函數可以將這兩個函數組合在一起。我們將 multiplyBy2add 作為參數傳給 compose,得到一個新的函數 addThenMultiply,該函數先將其參數加 1,然後再將結果乘以 2。最後,我們調用 addThenMultiply(2) ,得到 6

面向切面編程

面向切面編程是一種將橫切關註點與業務邏輯分離的編程方式。這種方式可以提高代碼的可維護性和可擴展性

function logExecutionTime(fn) {
    return function() {
        console.time('Execution time');
        let result = fn.apply(null, arguments);
        console.timeEnd('Execution time');
        return result;
    }
}

function add(num1, num2) {
    return num1 + num2;
}

let timedAdd = logExecutionTime(add);
console.log(timedAdd(2, 3)); // 輸出 Execution time: 0.048ms 5

在上面的例子中,我們定義瞭兩個函數 logExecutionTimeaddlogExecutionTime 函數接受一個函數作為參數,並返回一個新的函數,該函數會在執行原函數時記錄其執行時間。我們將 add 函數作為參數傳給 logExecutionTime,得到一個新的函數 timedAdd,該函數在執行加法操作時會記錄其執行時間。最後,我們調用 timedAdd(2, 3) ,得到 5,並在控制臺輸出執行時間

函數式編程

函數式編程是一種將計算過程看作是函數之間的組合的編程方式。這種方式可以提高代碼的可讀性和可維護性,減少副作用和狀態變量的使用

let numbers = [1, 2, 3, 4, 5];

let sum = numbers.reduce(function(acc, num) {
    return acc + num;
}, 0);

console.log(sum); // 輸出 15

在上面的例子中,我們使用瞭 JavaScript 內置的 reduce 函數,實現瞭對數組中所有數字的求和。reduce 函數接受兩個參數:一個回調函數和一個初始值。回調函數接受兩個參數:累加器和當前元素,返回值會被作為下一次調用回調函數時的累加器參數。在這個例子中,我們使用匿名函數作為回調函數,實現瞭將累加器和當前元素相加的操作。最後,我們將初始值設為 0,得到瞭數組中所有數字的和

閉包

閉包是指一個函數可以訪問其定義時的作用域中的變量和參數。這種方式可以實現局部變量的封裝和保護,提高代碼的安全性和穩定性

在上面的例子中,我們使用瞭閉包來實現函數柯裡化函數作為返回值。具體來說,我們定義瞭一個函數 add,它接受一個參數 num1,並返回一個匿名函數,該函數接受一個參數 num2,並將其與 num1 相加。這樣,我們就可以將 add(5) 賦值給變量 add5,得到一個新的函數,該函數可以將其參數與 5 相加

閉包的使用場景包括:

  • 封裝變量:閉包可以將變量封裝在函數內部,避免全局變量的污染和沖突。
  • 保護變量:閉包可以將變量保護起來,避免其被外部訪問和修改,提高代碼的安全性和穩定性。
  • 實現模塊化:閉包可以將一組相關的函數和變量封裝在一個函數內部,形成一個模塊,提高代碼的可維護性和可擴展性。
  • 實現柯裡化和函數組合:閉包可以將函數柯裡化和函數組合的實現變得更加簡單和直觀。
  • 實現面向對象編程:閉包可以將函數作為對象的方法,實現面向對象編程的方式。

總之,閉包是 JavaScript 中非常重要的概念,它可以幫助我們更好地組織代碼,提高代碼的可讀性、可維護性和可擴展性。但是,過度使用閉包也可能會導致代碼的復雜性和性能問題,因此需要謹慎使用。

復雜的例子

以下是一個更復雜的例子,它結合瞭多個高階函數的概念,包括函數作為參數傳遞、函數作為返回值、函數柯裡化、函數組合和面向切面編程

// 定義一個數組,包含一些數字
let numbers = [1, 2, 3, 4, 5];

// 定義一個函數,用於將數組中的每個元素加上一個指定的值
function add(amount) {
    return function(num) {
        return num + amount;
    }
}

// 定義一個函數,用於將數組中的每個元素乘以一個指定的值
function multiplyBy(factor) {
    return function(num) {
        return num * factor;
    }
}

// 定義一個函數,用於將數組中的所有元素相加
function sum(numbers) {
    return numbers.reduce(function(acc, num) {
        return acc + num;
    }, 0);
}

// 定義一個函數,用於記錄函數執行時間
function logExecutionTime(fn) {
    return function() {
        console.time('Execution time');
        let result = fn.apply(null, arguments);
        console.timeEnd('Execution time');
        return result;
    }
}

// 定義一個函數,用於組合多個函數
function compose() {
    let fns = Array.prototype.slice.call(arguments); // 將參數轉換為數組
    return function(x) {
        return fns.reduceRight(function(acc, fn) {
            return fn(acc);
        }, x);
    }
}

// 將數組中的每個元素加上 1,再將結果乘以 2,最後計算所有元素的和
let result = compose(logExecutionTime(sum), multiplyBy(2), add(1))(numbers);
console.log(result); // 輸出 Execution time: 0.131ms 30

詳細解釋:

  • 在上面的例子中,我們首先定義瞭一個包含一些數字的數組 numbers。然後,我們定義瞭三個函數 addmultiplyBysumaddmultiplyBy 分別返回一個匿名函數,該函數接受一個數字參數,並將其加上或乘以另一個數字。sum 函數使用 JavaScript 內置的 reduce 函數,計算數組中所有數字的和
  • 接下來,我們定義瞭一個函數 logExecutionTime,用於記錄函數執行時間。該函數接受一個函數作為參數,並返回一個新的函數,該函數在執行原函數時記錄其執行時間
  • 然後,我們定義瞭一個函數 compose,用於組合多個函數。該函數接受任意數量的函數作為參數,並返回一個新的函數,該函數可以將這些函數組合在一起,並按照從右到左的順序依次調用它們。在 compose 函數內部,我們使用瞭 Array.prototype.slice.call(arguments) 將參數列表轉換為數組,並使用 reduceRight 函數依次調用這些函數
  • 最後,我們使用函數柯裡化和函數組合,將 logExecutionTimesummultiplyByadd 函數組合在一起,實現瞭將數組中的每個元素加上 1,再將結果乘以 2,最後計算所有元素的和。我們將 numbers 數組作為參數傳給該函數,得到瞭最終的結果,並在控制臺輸出瞭執行時間

以上就是8個JavaScript的高階函數的運用分享的詳細內容,更多關於JavaScript高階函數的資料請關註WalkonNet其它相關文章!

推薦閱讀: