JS中的高階函數

「高階函數」是個咱們常常遇到的術語,英文名叫「higher-order function」,對於新手而言,還挺神祕。今天,咱們就來探討下高階函數。前端

定義

接收函數做爲參數或者返回函數的函數面試

大白話就是:bash

  1. 首先是個函數
  2. 參數或者返回值是函數

舉例子

咱們這裏舉兩個例子來覆蓋下上文的定義,其中,例一爲接收函數做爲參數的高階函數,例二爲返回函數的高階函數。前端框架

例一:函數做爲參數

咱們定義了一個叫evaluatesToFive的函數,接收兩個參數:第一個參數是一個數字,第二個參數是一個函數。在函數evaluatesToFive中,將參數一(數字)傳入參數二(函數)markdown

function evaluatesToFive(num, fn) {
  return fn(num) === 5;
}
複製代碼

使用的場景:閉包

function divideByTwo(num) {
  return num / 2;
}

evaluatesToFive(10, divideByTwo);
// true

evaluatesToFive(20, divideByTwo);
// false
複製代碼

哈哈,雖然函數自己用處不大,可是對描述高階函數來講,很簡單易懂。框架

例二:返回函數

本例中,咱們建立函數multiplyBy,接收一個數字做爲參數,並返回一個新的函數ide

function multiplyBy(num1) {
  return function(num2) {
    return num1 * num2;
  };
}
複製代碼

使用場景:函數

const multiplyByThree = multiplyBy(3);
const multiplyByFive = multiplyBy(5);

multipyByThree(10); // 30

multiplyByFive(10); // 50
複製代碼

是否是有點感受了,經過生成新的函數以達到更具體的目的。oop

更復雜的應用實例

本例中,咱們建立一個函數去檢測新用戶的註冊信息是否能經過檢驗規則:

  • 大於18歲
  • 密碼長度大於8
  • 贊成用戶協議

新用戶的註冊信息大概是這樣:

const newUser = {
  age: 24,
  password: 'some long password',
  agreeToTerms: true,
};
複製代碼

接下來,咱們來建立三個驗證函數,經過返回true,不然返回false

function oldEnough(user) {
  return user.age >= 18;
}

function passwordLongEnough(user) {
  return user.password.length >= 8;
}

function agreeToTerms(user) {
  return user.agreeToTerms === true;
}
複製代碼

接下來,該主角登場了,咱們須要建立一個高階函數來一次性完成全部的驗證。參數一是新用戶註冊信息,剩下的參數是咱們上文建立的三個驗證函數。在函數體中依次執行驗證:

function validate(obj, ...tests) {
  for (let i = 0; i < tests.length; i++) {
    if (tests[i](obj) === false) {
      return false;
    }
  }
  return true;
}
複製代碼

使用:

const newUser1 = {
  age: 40,
  password: 'tncy4ty49r2mrx',
  agreeToTerms: true,
};

validate(newUser1, oldEnough, passwordLongEnough, agreeToTerms);
// true

const newUser2 = {
  age: 40,
  password: 'short',
  agreeToTerms: true,
};

validate(newUser2, oldEnough, passwordLongEnough, agreeToTerms);
// false
複製代碼

到目前爲止,已經很棒了,繼續看下去,看咱們怎麼改進

繼續進化

上文中,咱們使用validate函數的時候須要傳入多個驗證函數(oldEnough, passwordLongEnough, agreeToTerms),這違反了最少知識原則(有興趣的同窗們能夠去了解下最少知識原則),看咱們怎麼將之繼續改進:

function createValidator(...tests) {
  return function(obj) {
    for (let i = 0; i < tests.length; i++) {
      if (tests[i](obj) === false) {
        return false;
      }
    }
    return true;
  };
}
複製代碼

這個createValidator函數牛逼了,它接收任意數量的函數做爲參數,返回值也是個函數。因此這個createValidator也是個高階函數。

使用:

const userValidator = createValidator(
  oldEnough,
  passwordLongEnough,
  agreeToTerms
);

userValidator(newUser1); // true
userValidator(newUser2); // false

複製代碼

看出什麼門道了沒?經過函數createValidator生成更具體的驗證函數userValidator,再使用userValidator去驗證新用戶的註冊信息。多麼精彩的高階函數!意猶未盡的同窗們能夠再學習下另外一個術語柯里化

結語

本小文,咱們一塊兒探討了JS中的高階函數,千萬不要覺得高階函數只是一道面試題。前端框架中很火的高階組件也是引用自高階函數。高階函數在咱們平常開發中常常會使用到,用好了,能夠將不少複雜的業務邏輯進行解耦,對於代碼的可讀性和可維護性頗有意義!文中也用到了閉包的知識,聰明的你發現了嗎?不要讓本身的知識永遠躺在面試題中哦!

相關文章
相關標籤/搜索