别再跟人说for循环不好了。
我必须说点什么。我时不时会看到一些帖子,内容大概是“循环不好,你应该用 filter、map 和 reduce 代替”——每次看到有人试图论证应该用这些函数式方法来处理所有事情时,我都气得咬牙切齿。
是的,这些函数式方法有其用途和合理之处。我并非反对你使用它们,而是反对在所有情况下都使用它们。很多情况下,如果你想编写高性能代码,for 循环始终是更快的选择。
map诸如 `get ()`filter和`get()` 之类的方法存在的意义reduce就在于防止传入的参数被修改。在函数式编程(FP)风格中,将数组传递给这些方法会返回一个新的集合,而原始数组则保持不变。
就 `map` 而言map(因为它似乎被滥用最严重且性能最差),它与 `for` 循环相比性能差异可能非常显著。原因是 `map` 会创建一个新的副本,每次迭代都会触发回调,从而消耗更多内存。而 `for` 循环直接处理迭代的对象,因此几乎没有额外开销。
有人创建了一个存储库,其中进行了比较工作,大量数据的结果令人震惊(如果你知道这些方法是如何工作的,那就一点也不奇怪了)。
在我的 Web 应用中,我倾向于使用 ` for` 循环map,filter而且reduce现在比以前用得更多。但我很清楚,在某些情况下,`for` 循环是更好的选择,因为 `for` 循环可以做到 `for` 循环无法做到的事情。
打破循环
你可能已经知道,可以使用关键字来停止 for 循环break。如果你使用 for 循环遍历数组,直到找到特定元素或达到设定的迭代次数,你可以break在循环体中执行 `end` 语句来停止循环。
相反map,filter它们reduce本质上是无法停止的;它们会不断迭代,直到遍历完数组中的每个元素。
异步循环
for 循环可以很容易地与 async/await 一起使用,这意味着您可以暂停循环,并让它等待 promise 解决后再继续迭代下一个值。
函数式方法一旦混入 async/await,就会变得非常不稳定。我觉得如果用 await 来等待累加器完成,或许能勉强运行map,filter但感觉不太对劲。reducereduce
使用 for 循环很简单,何必自找麻烦呢?而且,async/await 确实可以与各种 for 循环一起使用。
你在这样做吗?停止吧。
async function loadValues() {
let myValues = await getValuesFromApi();
myValues = myValues.map(value => {
value.total = value.price * value.quantity;
return value;
});
}
我见过太多次用 map 遍历对象数组,结果却把结果重新赋值给被映射的数组本身。map 的初衷map是创建数组的新副本,但很多人却把它map当成循环使用,最后把结果重新赋值给原来的变量,而不是创建一个新的变量。
如果你正在这样做,请立即停止。直接使用 for 循环吧,因为你现在做的就是循环,而且在这种情况下使用 for 循环没有任何好处map。
结论
在许多情况下,使用上述任何一种函数式方法代替传统的 for 循环,您都不会感觉到性能上的损失。如果您处理的数据量不是成千上万,100 毫秒的差别您根本察觉不到。
写你觉得舒服的内容,然后如果你发现性能不太理想,你可以使用浏览器开发者工具和常识来找出应用程序的哪些部分可以优化。
记住:过早优化是万恶之源。
文章来源:https://dev.to/beggars/stop-telling-people-for-loops-are-bad-279f