【譯】高階函數:利用Filter、Map和Reduce來編寫更易維護的代碼

原文:Higher Order Functions: Using Filter, Map and Reduce for More Maintainable Code
做者:Guido Schmitz
譯者:JeLewinejavascript

高階函數能夠幫助你加強你的JavaScript,讓你的代碼更具備聲明性。簡單來講,就是簡單,簡練,可讀。java

知道何時和怎樣使用高階函數是相當重要的。它們可讓你的代碼更容易理解和具備更好的可維護性。它們也可讓你很輕鬆的進行函數間的組合。咱們叫它複合函數,不過我不會在這裏進行詳細的介紹。在本文中,我將介紹JavaScript中三個最經常使用的高階函數:.filter().map().reduce數組

Filter

想象一下你正在編寫一段代碼:有一個寫滿不一樣人信息的列表,不過你想要過濾出一個大於等於18歲人的列表。函數

咱們的列表看起來就像下面這樣:ui

const people = [
 { name: ‘John Doe’, age: 16 },
 { name: ‘Thomas Calls’, age: 19 },
 { name: ‘Liam Smith’, age: 20 },
 { name: ‘Jessy Pinkman’, age: 18 },
];

咱們先來看看第一個高階函數是如何篩選出大於等於18歲人的栗子。爲了簡潔,我將使用ES6標準中的箭頭函數。這是一種很是簡潔的定義函數的方式,可讓咱們沒必要再寫functionreturn,以及一些括號、大括號和分號。code

const peopleAbove18 = (collection) => {
  const results = [];
 
  for (let i = 0; i < collection.length; i++) {
    const person = collection[i];
 
    if (person.age >= 18) {
      results.push(person);
    }
  }
  return results;
};

那如今若是咱們想要篩選出18~20歲之間的人呢?ip

const peopleBetween18And20 = (collection) => {
  const results = [];
 
  for (let i = 0; i < collection.length; i++) {
    const person = collection[i];
 
    if (person.age >= 18 && person.age <= 20) {
      results.push(person);
    }
  }
  return results;
};

你可能已經意識到了這裏有許多重複的代碼。咱們能夠抽象出一個通用的解決方案。這兩個函數有一些共同點。它們都在一個列表中進行迭代,而且在給定的條件下進行過濾。rem

"高階函數是一個將一個或多個函數做爲參數的函數"——ClojureBridgeget

咱們能夠經過使用更具聲明性的.filter()方法來改進咱們以前的函數。原型

const peopleAbove18 = (collection) => {
  return collection
    .filter((person) => person.age >= 18);
}

太棒了!咱們經過使用高階函數減小了許多額外的代碼。同時也讓咱們的代碼更具可讀性。咱們不在意如何過濾東西,咱們只是但願它被過濾。這篇文章稍後會介紹組合函數。

Map

讓咱們拿着剛剛的人員名單和一個其中喜歡喝咖啡的人員名單。

const coffeeLovers = [‘John Doe’, ‘Liam Smith’, ‘Jessy Pinkman’];

用命令式的實現方式就像下面這樣:

const addCoffeeLoverValue = (collection) => {
  const results = [];
 
  for (let i = 0; i < collection.length; i++) {
    const person = collection[i];
    if (coffeeLovers.includes(person.name)) {
      person.coffeeLover = true;
    } else {
      person.coffeeLover = false;
    }
 
    results.push(person);
  }
 
  return results;
};

咱們能夠利用.map()來讓代碼更具備聲明性:

const incrementAge = (collection) => {
  return collection.map((person) => {
    person.coffeeLover = coffeeLovers.includes(person.name);
 
    return person;
  });
};

再說一遍,.map()是一個高階函數。它容許咱們將一個函數做爲參數傳遞。

Reduce

我敢打賭,當你知道何時和怎樣使用它的時候,你會喜歡上這個函數。.reduce()很酷,上面提到的的大部分函數均可以經過它來實現。

讓咱們先舉一個簡單的栗子。咱們想計算全部人年齡的和。固然了,咱們仍是會首先看看如何用命令式的方式實現。它基本上就是經過循環來增長總年齡變量。

const sumAge = (collection) => {
  let num = 0;
 
  collection.forEach((person) => {
    num += person.age;
  });
 
  return num;
}

接下來是使用.reduce()的聲明式方法:

const sumAge = (collection) => collection.reduce((sum, person) => {
 return sum + person.age;
}, 0);

咱們甚至可使用.reduce()來建立咱們本身的.map().filter()

const map = (collection, fn) => {
  return collection.reduce((acc, item) => {
    return acc.concat(fn(item));
  }, []);
}
const filter = (collection, fn) => {
  return collection.reduce((acc, item) => {
    if (fn(item)) {
      return acc.concat(item);
    }
 
    return acc;
  }, []);
}

一開始這一起可能比較難理解。不過,.reduce()作的基本上就是以一個集合和一個定義了初始值的變量開始。而後,遍歷該集合並將值添加到變量中去。

組合map,filter和reduce

太好了,這些函數咱們都有了。並且很重要的一點是,他們都存在於JavaScript的數組原型上。這意味着咱們能夠同時使用它們。這可讓咱們輕鬆建立各類可複用的函數,減小編寫某些功能所須要的代碼量。

咱們已經討論過了如何利用.filter()來過濾出大於等於18歲的人;利用.map()來添加coffeeLover屬性;經過.reduce()來計算全部人年齡的和。如今,咱們寫一點代碼將這三個步驟合併起來。

const people = [
 { name: ‘John Doe’, age: 16 },
 { name: ‘Thomas Calls’, age: 19 },
 { name: ‘Liam Smith’, age: 20 },
 { name: ‘Jessy Pinkman’, age: 18 },
];
const coffeeLovers = [‘John Doe’, ‘Liam Smith’, ‘Jessy Pinkman’];
const ageAbove18 = (person) => person.age >= 18;
const addCoffeeLoverProperty = (person) => {
 person.coffeeLover = coffeeLovers.includes(person.name);
 
 return person;
}
const ageReducer = (sum, person) => {
 return sum + person.age;
}, 0);
const coffeeLoversAbove18 = people
 .filter(ageAbove18)
 .map(addCoffeeLoverProperty);
const totalAgeOfCoffeeLoversAbove18 = coffeeLoversAbove18
 .reduce(ageReducer);
const totalAge = people
 .reduce(ageReducer);

若是你用命令式方法的話,你最後會寫一堆重複代碼。

經過.map().reduce().filter()來建立函數的思惟將會極大的提升你的代碼質量。並且能夠增長可讀性。你根本沒必要在乎函數內到底發生了什麼,它很是容易理解。

相關文章
相關標籤/搜索