“高階函數”是個我們經常遇到的術語,英文名叫“higher-order function”,對於新手而言,還挺神秘。今天,我們就來探討下高階函數。
定義
接收函數作為參數或者返回函數的函數
大白話就是:
- 首先是個函數
- 參數或者返回值是函數
舉例子
我們這裡舉兩個例子來覆蓋下上文的定義,其中,例一為接收函數作為參數的高階函數,例二為返回函數的高階函數。
例一:函數作為參數
我們定義了一個叫evaluatesToFive的函數,接收兩個參數:第一個參數是一個數字,第二個參數是一個函數。在函數evaluatesToFive中,將參數一(數字)傳入參數二(函數)
<code>function evaluatesToFive(num, fn) {
return fn(num) === 5;
}/<code>
使用的場景:
<code>function divideByTwo(num) {
return num / 2;
}
evaluatesToFive(10, divideByTwo);
// true
evaluatesToFive(20, divideByTwo);
// false/<code>
哈哈,雖然函數本身用處不大,但是對描述高階函數來說,很簡單易懂。
例二:返回函數
本例中,我們創建函數multiplyBy,接收一個數字作為參數,並返回一個新的函數
<code>function multiplyBy(num1) {
return function(num2) {
return num1 * num2;
};
}/<code>
使用場景:
<code>const multiplyByThree = multiplyBy(3);
const multiplyByFive = multiplyBy(5);
multipyByThree(10); // 30
multiplyByFive(10); // 50/<code>
是不是有點感覺了,通過生成新的函數以達到更具體的目的。
更復雜的應用實例
本例中,我們創建一個函數去檢測新用戶的註冊信息是否能通過檢驗規則:
- 大於18歲
- 密碼長度大於8
- 同意用戶協議
新用戶的註冊信息大概是這樣:
<code>const newUser = {
age: 24,
password: 'some long password',
agreeToTerms: true,
};/<code>
接下來,我們來創建三個驗證函數,通過返回true,否則返回false
<code>function oldEnough(user) {
return user.age >= 18;
}
function passwordLongEnough(user) {
return user.password.length >= 8;
}
function agreeToTerms(user) {
return user.agreeToTerms === true;
}/<code>
接下來,該主角登場了,我們需要創建一個高階函數來一次性完成所有的驗證。參數一是新用戶註冊信息,剩下的參數是我們上文創建的三個驗證函數。在函數體中依次執行驗證:
<code>function validate(obj, ...tests) {
for (let i = 0; i < tests.length; i++) {
if (tests[i](obj) === false) {
return false;
}
}
return true;
}/<code>
使用:
<code>
到目前為止,已經很棒了,繼續看下去,看我們怎麼改進
繼續進化
上文中,我們使用validate函數的時候需要傳入多個驗證函數(oldEnough, passwordLongEnough, agreeToTerms),這違反了最少知識原則(有興趣的同學們可以去了解下最少知識原則),看我們怎麼將之繼續改進:
<code>function createValidator(...tests) {
return function(obj) {
for (let i = 0; i < tests.length; i++) {
if (tests[i](obj) === false) {
return false;
}
}
return true;
};
}/<code>
這個createValidator函數牛逼了,它接收任意數量的函數作為參數,返回值也是個函數。所以這個createValidator也是個高階函數。
使用:
<code>const userValidator = createValidator(
oldEnough,
passwordLongEnough,
agreeToTerms
);
userValidator(newUser1); // true
userValidator(newUser2); // false/<code>
看出什麼門道了沒?通過函數createValidator生成更具體的驗證函數userValidator,再使用userValidator去驗證新用戶的註冊信息。多麼精彩的高階函數!意猶未盡的同學們可以再學習下另一個術語柯里化!
結語
本小文,我們一起探討了JS中的高階函數,千萬不要以為高階函數只是一道面試題。前端框架中很火的高階組件也是引用自高階函數。高階函數在我們日常開發中經常會使用到,用好了,可以將很多複雜的業務邏輯進行解耦,對於代碼的可讀性和可維護性很有意義!文中也用到了閉包的知識,聰明的你發現了嗎?不要讓自己的知識永遠躺在面試題中哦!
以上內容都是我自己的一些感想,分享出來歡迎大家指正,順便求一波關注,有問題或者需要學習資料的夥伴可以~
敲黑板
關注 +轉發+私信“Java”
關注 +轉發+私信“Java”
關注 +轉發+私信“Java”
閱讀更多 即將禿頭的Java程序員 的文章