简体   繁体   English

有时 array.forEach() 比 array.map() 更好吗?

[英]Are there times when array.forEach() is better than array.map()?

In Javascript, I've been reading different articles on when to use forEach vs map on an array.在 Javascript 中,我一直在阅读有关何时在数组上使用forEachmap不同文章。 General consensus appears to be if you simply want to read each element of an array, use forEach .普遍的共识似乎是,如果您只想读取数组的每个元素,请使用forEach If you actually want to modify the data, use map .如果您确实要修改数据,请使用map Some even go so far to say always use map when you can, it's safer & faster.有些人甚至说尽可能使用map ,这样更安全、更快。

In my case, all I want to do is update a single property in each element.就我而言,我想要做的就是更新每个元素中的单个属性。

 var arr = [{ firstName: 'Tom', lastName: 'Washington', fullName: undefined }, { firstName: 'Bill', lastName: 'Smith', fullName: undefined }, { firstName: 'Jim', lastName: 'Jones', fullName: undefined }]; // arr.forEach((person) => { // person.fullName = `${person.lastName}, ${person.firstName}`; // }); var newArr = arr.map((person) => { return {...person, fullName: `${person.lastName}, ${person.firstName}`}; }); console.log(arr); console.log(newArr);

What I'm having a hard time understanding is why is the map approach preferred?我很难理解的是为什么首选map方法? By using forEach , I'm updating the data in place.通过使用forEach ,我正在更新数据。 With map , I'm creating a whole new array with all new elements.使用map ,我正在创建一个包含所有新元素的全新数组。 I understand this is preferred if you want to retain the original array, or you now have the option to do chaining if you want to perform additional operations on the array.我知道如果您想保留原始数组,这是首选,或者如果您想对数组执行其他操作,现在可以选择进行链接。 But if I don't care about any of that, why isn't forEach preferred?但如果我不关心这些,为什么不喜欢forEach呢?

They're likely calling map "safer" because it adheres to a functional programming model.他们可能会称map “更安全”,因为它遵循函数式编程模型。 In functional programming, most, if not all, data is immutable;在函数式编程中,大多数(如果不是全部)数据是不可变的; programming is a matter of creating new data from existing data, not modifying it in place.编程是从现有数据创建新数据的问题,而不是就地修改它。

The safety benefit comes in cases where you might not be the sole owner of the data.在您可能不是数据的唯一所有者的情况下,安全优势就会出现。 If your function receives an array from the caller, modifying it in place changes the caller's version of the array, not just your own (because they're really the same array).如果您的函数从调用者那里接收到一个数组,就地修改它会更改调用者的数组版本,而不仅仅是您自己的(因为它们实际上是同一个数组)。 And if they received it as an argument as well, it changes their caller's array as well (because it's all the same array).如果他们接受它作为参数传递中,也改变了他们的呼叫者的阵列,以及(因为它是所有相同的阵列)。 Ultimately this can lead to someone twelve hops away calling a function with their array, expecting it to remain unchanged, being surprised when it gets modified, and not having an easy way to determine what modified it.这最终会导致某人12个跳以外调用他们的阵列功能,希望当它被修改了它保持不变,感到惊讶,并没有一个简单的方法来确定哪些修改它。

While JavaScript is not a functional language, it offers functional paradigms so you can write in a functional style.虽然 JavaScript 不是函数式语言,但它提供了函数式范例,因此您可以以函数式风格进行编写。 If you're consistent about it, this sort of unexpected action-at-a-distance doesn't happen, and it's easier to reason about your code.如果您对此保持一致,则不会发生这种意外的远距离动作,并且更容易对您的代码进行推理。

This is particularly important for libraries;这对图书馆尤其重要; with a library, you don't want to assume the caller isn't programming functionally, so by behaving functionally, you avoid the risk of breaking their assumptions.对于库,您不想假设调用者没有按功能进行编程,因此通过按功能进行操作,您可以避免破坏他们的假设的风险。

That said, if you're not using a functional style, and you're not making a library to redistribute, then action-at-a-distance will always be a risk, and being partially functional does very little for you, so you should just choose the right tool for the job;也就是说,如果你没有使用函数式风格,并且你没有制作一个重新分发的库,那么远距离操作总是有风险的,而部分功能对你来说几乎没有,所以你应该为工作选择合适的工具; forEach for read only or to modify in place, map to create a new array. forEach为只读或就地修改, map创建一个新数组。

One last note: In theory, map might make code faster, despite constructing new arrays.最后一点:理论上,尽管构建了新数组,但map可能会使代码更快。 When the array is guaranteed to be created and destroyed within one function, the JIT optimizer has an easier time with lifetime analysis, analyzing typical contents, etc., and could conceivably:当保证在一个函数内创建和销毁数组时,JIT 优化器可以更轻松地进行生命周期分析、分析典型内容等,并且可以想象:

  1. Optimize intermediate arrays out completely (five map s might only make one new array)彻底优化中间数组(五个map可能只生成一个新数组)
  2. Specialize the array to the contents, length, etc. (possible with arrays received from outside, but harder to do consistently)将数组专门化为内容、长度等(可能使用从外部接收的数组,但更难做到一致)

I wouldn't count on such optimizations from map (don't decide which to use on that basis), but actual functional languages derive benefits like this from the immutability guarantees they enforce, and JavaScript JIT engines could take advantage of the same "guarantees" when they can observe they're adhered to in practice.我不会指望map这种优化(不要在此基础上决定使用哪个),但实际的函数式语言从它们强制执行的不变性保证中获得这样的好处,并且 JavaScript JIT 引擎可以利用相同的“保证” “当他们能够观察到时,他们就会在实践中得到遵守。

array.forEach simply iterates over the array while array.map() is making copy of that array, creating a callback function for every element hence you can do something like: array.forEach只是简单地遍历数组,而array.map()正在制作该数组的副本,为每个元素创建一个回调函数,因此您可以执行以下操作:

array.map( x => x*2 ) array.map( x => x*2 )

now you get brand new array with every value multiplied by 2现在你得到了一个全新的数组,每个值都乘以 2

Just taking by an example.只是举个例子。

forEach() may be preferable when you're not trying to change the data in your array, but instead want to just do something with it — like saving it to a database or logging it out:当您不想更改数组中的数据,而只想对其进行处理时, forEach()可能更可取——例如将其保存到数据库或将其注销:

 let arr = ['a', 'b', 'c', 'd']; arr.forEach((letter) => { console.log(letter); }); // a // b // c // d

And map() might be preferable when changing or altering data.在更改或更改数据时, map()可能更可取。 Not only is it faster but it returns a new Array.它不仅速度更快,而且返回一个新的数组。 This means we can do cool things like chaining on other methods ( map(), filter(), reduce() , etc.)这意味着我们可以做一些很酷的事情,比如链接其他方法( map(), filter(), reduce()等)

 let arr = [1, 2, 3, 4, 5]; let arr2 = arr.map(num => num * 2).filter(num => num > 5); // arr2 = [6, 8, 10]

What we're doing above is first mapping over arr and multiplying every element in the array times 2. After this, we filter through the array and only save the elements that are greater than 5. This leaves us with a final arr2 of [6,8,10] .我们上面所做的是首先映射 arr 并将数组中的每个元素乘以 2。此后,我们过滤数组并只保存大于 5 的元素。这给我们留下了最终的arr2 [6,8,10]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM