有没有什么时候array.forEach()比array.map()好?

时间:2019-01-25 21:07:26

标签: javascript arrays foreach

在Javascript中,我一直在阅读有关何时在数组上使用forEachmap的不同文章。一般共识似乎是,如果您只是想读取数组的每个元素,请使用forEach。如果您实际上要修改数据,请使用map。甚至有人说,尽可能使用map,它更安全,更快捷。

就我而言,我要做的就是更新每个元素中的单个属性。

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);

我很难理解的是为什么首选map方法?通过使用forEach,我就可以更新数据了。使用map,我将创建一个包含所有新元素的全新数组。我知道如果要保留原始数组是首选方法,或者如果要在数组上执行其他操作,现在可以选择链接。但是,如果我什么都不关心,为什么forEach不会被优先使用?

3 个答案:

答案 0 :(得分:2)

他们可能称map为“安全”,因为它遵循功能性编程模型。在函数式编程中,大多数(如果不是全部)数据是不可变的。编程是从现有数据中创建新数据,而不是就地进行修改的问题。

如果您可能不是数据的唯一所有者,则可以享受安全保障。如果您的函数从调用方收到一个数组,则对其进行修改会更改该调用方的数组版本,而不仅仅是您自己的版本(因为它们实际上是同一数组)。如果他们也将其作为参数接收,它也会更改其调用方的数组(因为它们都是相同的数组)。最终,这可能导致某人十二跳远地用其数组调用函数,期望它保持不变,在被修改时会感到惊讶,并且无法轻松地确定对它们进行了什么修改。 >

虽然JavaScript不是一种功能语言,但它提供了功能范例,因此您可以以功能风格进行编写。如果您对此保持一致,则不会发生这种意外的远距离操作,并且更容易推理代码。

这对图书馆尤为重要;使用库,您不希望假定调用者的功能不是在编程,因此通过行为,可以避免破坏他们的假设的风险。

也就是说,如果您不使用功能性样式,并且没有在进行重新分配的库,那么按距离进行动作将始终是一种风险,而部分功能性对您几乎没有任何帮助,因此您应该只选择适合该工作的工具; forEach只读或进行修改,map创建新数组。

最后一点:理论上,map可以使代码更快,尽管构造了新的数组。当保证在一个函数中创建和销毁数组时,JIT优化器可以更轻松地进行生命周期分析,分析典型内容等,并且可以想到:

  1. 完全优化中间阵列(五个map可能只创建一个新阵列)
  2. 根据内容,长度等对数组进行专业化处理(可能是从外部收到的数组,但是很难做到一致)

我不会指望map进行这样的优化(不要在此基础上决定使用哪种优化),但是实际的功能语言会从它们执行的不变性保证中获得类似的好处,而JavaScript JIT引擎可以当他们看到自己在实践中得到遵守时,可以利用相同的“保证人”。

答案 1 :(得分:0)

array.forEach 只是在 array.map()复制该数组的同时遍历该数组,为每个元素创建一个回调函数,因此您可以执行某些操作喜欢:

array.map(x => x * 2)

现在您将获得一个全新的数组,每个值都乘以2

答案 2 :(得分:0)

仅举一个例子。

forEach()在您不尝试更改数组中的数据而只想对其进行更改时可能更可取,例如将其保存到数据库或注销:

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


// a
// b
// c
// d

并且map()在更改或更改数据时可能更可取。它不仅速度更快,而且还会返回一个新的数组。这意味着我们可以做一些很酷的事情,例如在其他方法上链接(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]

我们在上面所做的是首先在arr上进行映射,并将数组中的每个元素乘以2。此后,我们对数组进行过滤,仅保存大于5的元素。这给我们留下了最后一个{ arr2中的{1}}。