数组方法

你有一个价格列表,想要第二个列表,其中每个价格都添加了税。你可以编写一个 for 循环来遍历数组、计算总和,然后将每个结果推送到新数组中。这样可以工作,但对于一个小想法来说需要太多的代码:取每个项目并改变它。数组方法正是为这类工作而设计的内置工具。它们让你说出你想对列表做什么,而不需要详细说明实现循环,本章涵盖了你每天都会用到的那些。它们直接基于数组和函数构建,所以把两者都放在手边。
map:改变每个项目
map 是一个**方法**:一个属于数组的函数,对其进行操作。map 通过将每个项目运行通过你给它的一个小函数来构建一个新数组,并收集结果。你传递给它那个函数,它一次手交给你一个项目。
假设你有一些价格,想要每个都翻倍:
const prices = [2, 4, 6];
const doubled = prices.map((price) => price * 2);
console.log(doubled); // [4, 8, 12](price) => price * 2 部分是一个箭头函数:一个短函数,它接受一个项目(price)并返回它应该变成什么(price * 2)。map 对每个项目调用一次,并将每个答案放在新数组的相同位置。
map 获取一个列表,给你一个相同长度的新列表,每个项目都通过你的小函数运行。箭头函数说出每个项目变成什么,map 按顺序对所有项目做这件事。每当你发现自己写一个循环只是为了构建第二个列表时,就可以使用它。 filter:保留通过测试的项目
map 改变每个项目,而 filter 只保留其中一些。你给它一个函数,为每个项目回答是或否,filter 从只有回答"是"的项目中构建一个新数组。
const scores = [40, 75, 90, 55, 88];
const passing = scores.filter((score) => score >= 60);
console.log(passing); // [75, 90, 88]函数 (score) => score >= 60 为每个分数返回 true 或 false。filter 保留返回 true 的项目,丢弃其余的。新数组可以比原数组更短,它永远不会改变顺序。
filter 保留通过测试的项目,丢弃其余的,所以新数组通常更短。你的函数为每个项目回答是或否,只有"是"的项目才能通过。它永远不会重新排序任何内容,所以存活的项目保持开始时的顺序。 reduce:化简为一个值
map 和 filter 都交给你一个数组。reduce 是将数组塌缩为一个单一值的:一个总和、一个最大值、一个连接的字符串。它比其他的更容易让人困惑,所以值得慢慢来。
reduce 遍历数组,同时携带一个运行结果。在每个项目上,它问:给定到目前为止的结果,以及这个项目,新结果是什么?
const prices = [10, 20, 30];
const total = prices.reduce((sum, price) => sum + price, 0);
console.log(total); // 60函数得到两件事:sum,到目前为止的运行总和,和 price,当前项目。它返回 sum + price,这成为下一个项目的新运行总和。末尾的 0 是总和开始的地方。所以它是 0 + 10,然后 10 + 20,然后 30 + 30,落在 60。
reduce 通过列表携带一个运行结果,并在每个项目处更新它。回调获取到目前为止的结果加上当前项目,并返回新结果。最后一个论点是你开始的地方,通常是 0 作为总和,当我大声读出来一步一步时这个对我点击了。 find、some 和 every
这三个是 filter 的近亲:它们在数组上运行测试,但不是一个新数组,它们回答一个更狭义的问题。
find 给你通过测试的第一个项目,不是所有项目的列表。some 和 every 回答关于整个数组的是或否问题。
const scores = [40, 75, 90, 55];
const firstPass = scores.find((score) => score >= 60);
console.log(firstPass); // 75
const anyPass = scores.some((score) => score >= 60);
console.log(anyPass); // true
const allPass = scores.every((score) => score >= 60);
console.log(allPass); // falsefind 返回第一个匹配的项目(75)。some 问"有任何项目通过吗?"并返回 true,因为至少有一个通过。every 问"它们都通过了吗?"并返回 false,因为 40 和 55 没有通过。
find 给你通过的第一个项目,不是整个列表。some 问"有任何通过吗?"而 every 问"都通过了吗?",两者都用 true 或 false 回答。当你想要一个项目或一个是或否答案,不是一个过滤后的数组时使用这些。 链接和保持可读性
上面的方法共享一个设计,一旦你结合它们就会获得回报:每一个都返回一个新值并让原始数组不动。
map、filter 和其他的永远不会改变你开始的数组。它们给你一个新数组(或一个值)并让原始的单独。
const prices = [10, 20, 30];
const doubled = prices.map((price) => price * 2);
console.log(doubled); // [20, 40, 60]
console.log(prices); // [10, 20, 30]因为 map 和 filter 都交给你一个数组,你可以把它们排成一队:先过滤,然后映射幸存者。
const prices = [10, 20, 30, 40];
const bigDoubled = prices.filter((price) => price >= 20).map((price) => price * 2);
console.log(bigDoubled); // [40, 60, 80]filter 和 map 都返回数组,你可以链接它们:先过滤,然后映射剩下的。从上到下,一次一步读链。 接下来去哪里
map、filter 和 reduce 涵盖了你在列表中做的大多数事情:转换它、缩小它或塌缩它。find、some 和 every 回答更狭义的问题。一旦这些感到自然,你数组上的大多数 for 循环变成一行或两行,说出你的意思。
自然的下一步是对象,其中数组开始保留比普通数字和字符串更丰富的项目,这些相同的方法在它们上继续工作。如果这里的任何回调语法感到摇摇欲坠,通过函数的一次通过使其余的点击到位。

