通过这三种方法,您可以避免在大多数情况下使用 for 和 forEach 。当你试图做一个 for 循环时,尝试用 map,filter 和 reduce 来组合试试。起初你可能很难做到这一点,因为它需要你学习一种新的思维方式,但一旦你得到它,事情会变得更容易。
愚人码头注:JavaScript 函数式编程建议看看以下几篇文章
简单的示例 const numbers = [0, 1, 2, 3, 4, 5, 6]; const doubledNumbers = numbers.map(n => n * 2); // [0, 2, 4, 6, 8, 10, 12] const evenNumbers = numbers.filter(n => n % 2 === 0); // [0, 2, 4, 6] const sum = numbers.reduce((prev, next) => prev + next, 0); // 21通过组合 map,filter 和 reduce 来计算 10 分以上的学生成绩总和 sum :
const students = [ { name: "Nick", grade: 10 }, { name: "John", grade: 15 }, { name: "Julia", grade: 19 }, { name: "Nathalie", grade: 9 }, ]; const aboveTenSum = students .map(student => student.grade) // 我们将学生数组映射到他们成绩的数组中 .filter(grade => grade >= 10) // 我们过滤成绩数组以保持10分以上的元素 .reduce((prev, next) => prev + next, 0); // 我们将合计所有10分以上的成绩 console.log(aboveTenSum) // 44 -- 10 (Nick) + 15 (John) + 19 (Julia), 低于10的 Nathalie 被忽略 说明让我们考虑一下下列数组:
const numbers = [0, 1, 2, 3, 4, 5, 6]; Array.prototype.map() const doubledNumbers = numbers.map(function(n) { return n * 2; }); console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]这里发生了什么?我们在 numbers 这个数组中使用 .map 方法,map 将会迭代数组的每个元素,并传递给我们的函数。该函数的目标是生成并返回一个新的值,以便 map 可以替换掉原本的数组。
我们来解释一下这个函数,使之更清楚一点:
const doubleN = function(n) { return n * 2; }; const doubledNumbers = numbers.map(doubleN); console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]numbers.map(doubleN) 将会产生 [doubleN(0), doubleN(1), doubleN(2), doubleN(3), doubleN(4), doubleN(5), doubleN(6)] 而它们分别等同于 [0, 2, 4, 6, 8, 10, 12]。
注意: 如果你不需要返回一个新的数组, 且只想执行一个带有副作用的循环,使用 for / forEach 循环会更为符合你的需求。
Array.prototype.filter() const evenNumbers = numbers.filter(function(n) { return n % 2 === 0; // 如果 "n" 符合条件返回 true , 如果 "n" 不符合条件则 false 。 }); console.log(evenNumbers); // [0, 2, 4, 6]我们在 numbers 数组中使用 .filter 方法,过滤器遍历数组中的每个元素,并将其传递给我们的函数。函数的目标是返回一个布尔值,它将确定当前值是否被保留。过滤之后返回的数组将只包含保留值。
Array.prototype.reduce()reduce 方法的目标是将迭代数组中的所有元素,减少 到只留下单一值。如何聚合这些元素取决于你。
const sum = numbers.reduce( function(acc, n) { return acc + n; }, 0 // 累加器迭代变量的初始值 ); console.log(sum) //21就像 .map 和 .filter 方法一样, .reduce 方法被应用在数组上并接收一个函数做为第一个参数。
下面是一些差异:
.reduce 接受两个参数
第一个参数是一个函数,将在每个迭代步骤中被调用。
第二个参数是在第一个迭代步骤(读取下一个用的)的累加器变量的值(此处是 acc)。
函数参数
作为 .reduce 的第一个参数传递的函数需要两个参数。第一个(此处是 acc)是累加器变量,而第二个参数(n)则是当前元素。
累加器变量的值等于 上一次 迭代步骤中函数的返回值。在迭代过程的第一步,acc 等于你做为 .reduce 时第二个参数所传递的值(愚人码头注:也就是累加器初始值)。
进行第一次迭代acc = 0 因为我们把 0 做为 reduce 的第二个参数
n = 0 number 数组的第一个元素
函数返回 acc + n –> 0 + 0 –> 0
进行第二次迭代acc = 0 因为它是上次迭代所返回的值
n = 1 number 数组的第二个元素
函数返回 acc + n –> 0 + 1 –> 1
进行第三次迭代acc = 1 因为它是上次迭代所返回的值
n = 2 number 数组的第三个元素
函数返回 acc + n –> 1 + 2 –> 3
进行第四次迭代acc = 3 因为它是上次迭代所返回的值
n = 3 number 数组的第四个元素
函数返回 acc + n –> 3 + 3 –> 6
[…] 进行最后一次迭代acc = 15 因为它是上次迭代所返回的值
n = 6 number 数组的最后一个元素
函数返回 acc + n –> 15 + 6 –> 21
因为它是最后一个迭代步骤了, .reduce 将返回 21 。
扩展阅读 展开操作符 “…”