JavaScript中forEach和map详细讲解

作者:代码拾荒时间:2026-11-01 01:08:20浏览:317

本文详细解析JavaScript中数组遍历方法forEach和map的用法、底层原理及性能差异。通过对比两者在返回值、this指向及执行效率上的不同,帮助开发者根据实际需求选择合适的方法,并深入剖析其基于迭代器的实现机制。

基本用法

forEach与map均为JavaScript中常用的数组遍历手段,二者皆可对数组元素执行特定操作,然其使用范式及返回结果存在差异。

forEach

forEach系数组内置方法,旨在对数组内各元素依次执行回调逻辑。该函数不返回任何值,仅负责遍历数组并执行回调。

forEach之语法结构如下:

array.forEach(callback(currentValue, index, array), thisArg);

此处,callback指代需执行的函数,其接收三个参数:

  • currentValue:当前遍历之元素。
  • index:当前元素之索引。
  • array:当前遍历之数组本体。

thisArg为可选参数,用于指定回调执行时的this上下文。

forEach之返回值为undefined,并不生成新数组。

forEach与for循环功能相近,但前者更为简洁易读且安全,可有效规避数组越界及重复计算等常见问题。

下述示例演示利用forEach遍历数组并输出各元素:

const arr = [1, 2, 3];

arr.forEach((element) => {
  console.log(element);
});

map

map亦为数组方法,对每个元素执行回调后,将返回值存入新数组。

map语法如下:

array.map(callback(currentValue, index, array), thisArg);

其中,callback为执行函数,接收三个参数:

  • currentValue:当前处理元素。
  • index:当前元素索引。
  • array:当前遍历数组。

thisArg为可选参数,用于指定回调执行时的this值。

map返回新数组,其长度与原数组一致,各元素为回调处理后的结果。

下述示例演示利用map将数组元素各加1:

const arr = [1, 2, 3];

const newArr = arr.map((element) => {
  return element + 1;
});

console.log(newArr); // 输出[2, 3, 4]

可见,map生成新数组,并将原数组元素各加1。

剖析原理

forEach与map原理均基于数组迭代器,实为调用迭代器实现遍历。

JavaScript数组内置迭代器Array.prototype[@@iterator],返回迭代器对象以支持遍历。forEach与map均调用Array.prototype[@@iterator]获取迭代器对象,进而遍历。

forEach

调用forEach时,JavaScript引擎执行以下步骤:

  • 检查数组存在性,若不存在则抛出TypeError异常。
  • 检查首参数是否为函数,若非则抛出TypeError异常。
  • 检查第二参数是否为对象,若是则作为this值传递,否则this值为undefined。
  • 通过调用Array.prototype[@@iterator]获取迭代器对象。
  • 对迭代器中各元素依次执行回调,传递当前值、索引及原数组。
  • forEach不返回任何值。

下述为简化forEach实现代码:

Array.prototype.myForEach = function(callback, thisArg) {
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }
  for (var i = 0; i < this.length; i++) {
    callback.call(thisArg, this[i], i, this);
  }
};

可见,该实现利用for遍历数组,并通过call调用回调,传递当前值、索引及原数组。

map

map原理与forEach类似,均通过迭代器遍历,唯map将回调返回值存入新数组。以下剖析map原理。

调用map时,JavaScript引擎执行以下步骤:

  • 检查数组存在性,若不存在则抛出TypeError异常。
  • 检查首参数是否为函数,若非则抛出TypeError异常。
  • 检查第二参数是否为对象,若是则作为this值传递,否则this值为undefined。
  • 创建空数组以存储回调返回值。
  • 通过调用Array.prototype[@@iterator]获取迭代器对象。
  • 对迭代器中各元素依次执行回调,传递当前值、索引及原数组。
  • 将回调返回值存入新数组。
  • 返回新数组。

下述为简化map实现代码:

Array.prototype.myMap = function(callback, thisArg) {
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }
  var newArray = [];
  for (var i = 0; i < this.length; i++) {
    newArray.push(callback.call(thisArg, this[i], i, this));
  }
  return newArray;
};

可见,该实现除利用for遍历外,还创建新数组存储回调返回值,最终返回。

forEach和map的共同点

  • 均仅能遍历数组
  • 均循环遍历数组各项。
  • 每次执行匿名函数支持三参数:item(当前项),index(索引),arr(原数组)。
  • 匿名函数内this指向window。

forEach和map的不同点

  • forEach()无返回值,会修改原数组。

  • map()有返回值,返回新数组,不改变原数组,且不对空数组检测。

  • 总体而言map速度大于forEach()

  • 性能排序:for > forEach > map

总结

综上,forEach与map均基于数组迭代器实现,主要区别在于对回调处理。forEach执行回调时忽略返回值。map执行回调时将返回值存入新数组并返回。若需对元素操作并将结果存为新数组,应选map。若仅需执行操作无需存储结果,应选forEach。

至此关于JavaScript中forEach和map详细讲解的文章介绍完毕,更多相关js forEach和map内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

作者最新文章