百科狗-知识改变命运!
--

Array.prototype.forEach() - JavaScript Array 对象

是丫丫呀12个月前 (11-21)阅读数 20#技术干货
文章标签数组

Array.prototype.forEach()

forEach()方法对数组的每个元素执行一次提供的函数。

语法

arr.forEach(callback(currentValue [, index [, array]])[, thisArg]);

参数

callback为数组中每个元素执行的函数,该函数接收三个参数:currentValue数组中正在处理的当前元素。index可选数组中正在处理的当前元素的索引。array可选forEach()方法正在操作的数组。thisArg可选可选参数。当执行回调函数callback时,用作this的值。

返回值

undefined

描述

forEach()方法按升序为数组中含有效值的每一项执行一次callback函数,那些已删除或者未初始化的项将被跳过(例如在稀疏数组上)。

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

  1. 数组当前项的值
  2. 数组当前项的索引
  3. 数组对象本身

如果thisArg参数有值,则每次callback函数被调用时,this都会指向thisArg参数。如果省略了thisArg参数,或者其值为nullundefinedthis则指向全局对象。按照函数观察到this的常用规则,callback函数最终可观察到this值。

forEach()遍历的范围在第一次调用callback前就会确定。调用forEach后添加到数组中的项不会被callback访问到。如果已经存在的值被改变,则传递给callback的值是forEach()遍历到他们那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用shift()),之后的元素将被跳过——参见下面的示例。

forEach()为每个数组元素执行一次callback函数;与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()

这些数组方法则可以对数组元素判断,以便确定是否需要继续遍历:

  • every()
  • some()
  • find()
  • findIndex()

Array.prototype.forEach() - JavaScript Array 对象

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

示例

不对未初始化的值进行任何操作(稀疏数组)

如你所见,37之间空缺的数组单元未被forEach()调用callback函数,或进行任何其他操作。

const arraySparse = [1,3,,7];
let numCallbackRuns = 0;

arraySparse.forEach(function(element){
  console.log(element);
  numCallbackRuns++;
});

console.log("numCallbackRuns: ", numCallbackRuns);

// 1
// 3
// 7
// numCallbackRuns: 3

将 for 循环转换为 forEach

const items = ['item1', 'item2', 'item3'];
const copy = [];

// before
for (let i=0; i {
    if (Array.isArray(i))
      result.push(...flatten(i));
    else
      result.push(i);
  })
  
  return result;
}

// Usage
const problem = [1, 2, 3, [4, 5, [6, 7], 8, 9]];

flatten(problem); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

针对 promise 或 async 函数的使用备注

如果使用 promise 或 async 函数作为forEach()等类似方法的callback参数,最好对造成的执行顺序影响多加考虑,否则容易出现错误。

let ratings = [5, 4, 5];

let sum = 0;

let sumFunction = async function (a, b) {
    return a + b;
} 

ratings.forEach(async function(rating) {
    sum = await sumFunction(sum, rating);
})

console.log(sum);
// Expected output: 14
// Actual output: 0

Polyfill

forEach()是在第五版本里被添加到 ECMA-262 标准的;这样它可能在标准的其他实现中不存在,你可以在你调用forEach()之前插入下面的代码,在本地不支持的情况下使用forEach()。该算法是 ECMA-262 第5版中指定的算法。它假定Function.prototype.call()

// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
if (!Array.prototype.forEach) {

  Array.prototype.forEach = function(callback, thisArg) {

    var T, k;

    if (this == null) {
      throw new TypeError(' this is null or not defined');
    }

    // 1. Let O be the result of calling toObject() passing the
    // |this| value as the argument.
    var O = Object(this);

    // 2. Let lenValue be the result of calling the Get() internal
    // method of O with the argument "length".
    // 3. Let len be toUint32(lenValue).
    var len = O.length >>> 0;

    // 4. If isCallable(callback) is false, throw a TypeError exception. 
    // See: http://es5.github.com/#x9.11
    if (typeof callback !== "function") {
      throw new TypeError(callback + ' is not a function');
    }

    // 5. If thisArg was supplied, let T be thisArg; else let
    // T be undefined.
    if (arguments.length > 1) {
      T = thisArg;
    }

    // 6. Let k be 0
    k = 0;

    // 7. Repeat, while k 

鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com

免责声明:我们致力于保护作者版权,注重分享,当前被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!邮箱:344225443@qq.com)

图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

内容声明:本文中引用的各种信息及资料(包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主体(包括但不限于公司、媒体、协会等机构)的官方网站或公开发表的信息。部分内容参考包括:(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供参考使用,不准确地方联系删除处理!本站为非盈利性质站点,本着为中国教育事业出一份力,发布内容不收取任何费用也不接任何广告!)