JS基礎——高階函數

定義

高階函數是至少知足下面一個條件的函數:
一、接收一個或多個函數做爲參數。好比filter函數
二、返回一個函數。 好比bind函數
舉個例子:好比咱們要篩數組[1,2,3,4,5]中大於3的全部元素,咱們一般的實現方法爲:編程

let newArr = [];
for(let i = 0,len = arr.length; i < len; i++){
    arr[i] > 3 && newArr.push(arr[i])
}

而使用數組filter方法的話,只須要 let newArr = arr.filter((item) => {return item > 3})。固然咱們也能夠經過高階函數來本身實現:api

Array.prototype.myFilter = function (fn){
    let newArr = [];
    for(let i = 0,len = this.length; i < len; i++){
        fn(this[i]) && newArr.push(this[i])
    }
    return newArr;
}
[1,2,3,4,5].myFilter((item) => { return item > 3})

咱們能夠經過封裝高階函數來複用和簡化咱們的代碼。數組

柯里化

柯里化是將一個多參數的函數轉換成多個單參數的函數,這個函數會返回一個函數去處理下一個參數。也就是把fn(a,b,c)轉換爲newFn(a)(b)(c)這種形象。柯里化常見的應用有:參數複用、延遲計算。好比咱們有個拼接接口地址的函數:app

function getUrl(service,context,api){
    return service + context + api;
}
let loginUrl = getUrl('http://localhost:8080/','auth','/login')  
let logoutUrl = getUrl('http://localhost:8080/','auth','/logout')

每次前兩個參數的值都是同樣,咱們能夠柯里化來封裝下來達到參數複用:函數

function curry(fn){
    let args = Array.prototype.slice.call(arguments,1);    
    return function(){
        let innerArgs = Array.prototype.slice.call(arguments);
        let finalArgs = args.concat(innerArgs);
        if(finalArgs.length < fn.length){         //fn.length爲函數的參數個數
            return curry.call(this,fn,...finalArgs)
        }else{
            return fn.apply(null,finalArgs)
        }
    }
}
var getAuthUrl = curry(getUrl,'http://localhost:8080/','auth');
let loginUrl = getAuthUrl('/login')
let logoutUrl = getAuthUrl('/logout')

組合函數

組合函數相似於管道,多個函數的執行時,上一個函數的返回值會自動傳入到第二個參數繼續執行。好比咱們替換一個url中的參數:this

function replaceToken(str){
    return str.replace(/{token}/g,'123455')
}
function replaceAccount(str){
    return str.replace(/{account}/g,'xuriliang')
}
replaceAccount(replaceToken('http://localhost/api/login?token={token}&account={account}'))

咱們能夠利用這種嵌套的寫法來實現,但若是嵌套過多,代碼可讀性就不是很好了。固然咱們也能夠在一個函數裏分過程實現,不過這樣函數就不符合單一原則了。利用函數組合咱們能夠這樣寫:url

function compose() {
    var args = arguments;
    var start = args.length - 1;
    return function() {
        var i = start;
        var result = args[start].apply(this, arguments);
        while (i--) result = args[i].call(this, result);
        return result;
    }
}
compose(replaceToken,replaceAccount)('http://localhost/api/login?token={token}&account={account}')

組合函數使得咱們可使用一些通用的函數,組合出各類複雜運算。這也是函數編程中pointfree的概念。prototype

相關文章
相關標籤/搜索