for of、for in、forEach、map的特性与区别

null

Posted by NeptLiang on January 21, 2021

0x00 前言

看公司项目源码的时候看到一个forEach方法,故往MDN了解一下,然后在MDN的介绍里又看到for...offor...inmap,在此总结一下它们的特性、区别及如何选择该用哪个


0x01 Array.prototype.map()

map() 方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。

参数

  • callback
    生成新数组元素的函数,使用三个参数:
    • currentValue
      callback 数组中正在处理的当前元素
    • index 可选
      callback 数组中正在处理的当前元素的索引
    • array 可选
      map 方法调用的数组
  • thisArg 可选
    执行 callback 函数时值被用作this

因为map生成一个新数组,当你不打算使用返回的新数组却使用map是违背设计初衷的,请用forEach或者for-of替代。你不该使用map: A)你不打算使用返回的新数组,或/且 B) 你没有从回调函数中返回值


0x02 Array.prototype.forEach()

forEach() 方法对数组的每个元素执行一次给定的函数

可依次向 callback 函数传入三个参数:

  1. 数组当前项的
  2. 数组当前项的索引(可选)
  3. 数组对象本身(可选)

forEach() 为每个数组元素执行一次 callback 函数;与 map() 或者 reduce() 不同的是,它总是返回 undefined,并且不可链式调用。其典型用例是在一个调用链的最后执行副作用(side effects,函数式编程上,指函数进行 返回结果值 以外的操作)。

forEach() 被调用时,不会改变原数组,也就是调用它的数组(尽管 callback 函数在被调用时可能会改变原数组)。(译注:此处说法可能不够明确,具体可参考EMCA语言规范:’forEach does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn.’,即 forEach 不会直接改变调用它的对象,但是那个对象可能会被 callback 函数改变。)

注意: 除了抛出异常以外,没有办法中止或跳出 forEach() 循环。如果你需要中止或跳出循环,forEach() 方法不是应当使用的工具。

若你需要提前终止循环,你可以使用:

  • 一个简单的 for 循环
  • for...of / for...in 循环
  • Array.prototype.every()
  • Array.prototype.some()
  • Array.prototype.find()
  • Array.prototype.findIndex()

译者注:只要条件允许,也可以使用 filter() 提前过滤出需要遍历的部分,再用 forEach() 处理。


0x03 for...of

for...of语句可迭代对象(包括 ArrayMapSetStringTypedArrayarguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句

无论是for...in还是for...of语句都是迭代一些东西。它们之间的主要区别在于它们的迭代方式

for...in 语句以任意顺序迭代对象的可枚举属性

for...of 语句遍历可迭代对象定义要迭代的数据


0x04 for...in

for...in语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性

提示for...in不应该用于迭代一个关注索引顺序的 Array

for ... in是为遍历对象属性而构建的,不建议与数组一起使用,数组可以用Array.prototype.forEach()for ... of,那么for ... in的到底有什么用呢?

它最常用的地方应该是用于调试,可以更方便的去检查对象属性(通过输出到控制台或其他方式)。尽管对于处理存储数据,数组更实用些,但是你在处理有key-value数据(比如属性用作“键”),需要检查其中的任何键是否为某值的情况时,还是推荐用for ... in


0xff 总结

1. forEach

  • 针对数组
  • 总是返回 undefined
  • 没有办法中止或跳出 forEach() 循环

2. map

  • 针对数组
  • 不打算使用返回的新数组却使用map是违背设计初衷的

3. for...of

针对可迭代对象(包括 ArrayMapSetStringTypedArrayarguments 对象等等)

4. for...in

针对对象

5. 如何选择

针对对象 for...in
针对数组 需要返回新数组 map
不需要返回新数组 需要中止或跳出循环 for...of
for 循环
不需要中止或跳出循环: forEach
for...of
for 循环

//End of Article


参考文献

公众号二维码