javascript 数组方法(map、forEach、reduce 等)的迭代顺序是否确定?

cra*_*tin 3 javascript arrays iteration specifications deterministic

使用其中一种本机方法(map、forEach、reduce、filter 等)遍历数组的顺序是否具有确定性并由标准保证?

EG,是否保证 foo、bar、baz 和 qux 是[0, 2, 6, 12]

const a = [1, 2, 3, 4];
const foo = a.map((item, index) => item * index);
const bar = []; a.forEach((item, index) => bar[index] = item * index);
const baz = []; a.reduce((total, item, index) => baz[index] = item * index, 0);
const qux = []; a.filter((item, index) => qux[index] = item * index);
// etc
Run Code Online (Sandbox Code Playgroud)

(这些是(非常)人为的例子)

som*_*ome 5

为数组中存在的每个元素按升序调用回调函数。它要求缺失的元素。(缺少元素?是的,JavaScript 处理稀疏数组)

var test = [];
test[30] = 'Test'; // sparse array, only one element defined.

test.forEach(
  function(value){
    console.log(value); // will only be called one time.
  }
);
Run Code Online (Sandbox Code Playgroud)

来自标准:ECMA-262

22.1.3.10 Array.prototype.forEach ( callbackfn [ , thisArg ] )

注 1

callbackfn应该是一个接受三个参数的函数。 forEach为数组中的每个元素按升序调用callbackfn一次。callbackfn仅针对实际存在的数组元素调用;不要求缺少数组元素

如果提供了thisArg参数,它将用作每次调用callbackfnthis值。如果未提供,则使用undefined

callbackfn使用三个参数调用:元素的值、元素的索引和被遍历的对象。

forEach不会直接改变调用它的对象,但该对象可能会通过调用callbackfn 来改变

当使用一两个参数调用forEach方法时,将采取以下步骤:

  1. 让 O 成为?ToObject(这个值)。
  2. 让 len ? ToLength(? Get(O, "length"))。
  3. 如果 IsCallable(callbackfn) 为false,则抛出TypeError异常。
  4. 如果提供了 thisArg,则设 T 为 thisArg;否则让 T 为undefined
  5. 令 k 为 0。
  6. 重复,而 k < len a。让 Pk 吧!ToString(k)。湾 让 kPresent 是?HasProperty(O, Pk)。C。如果 kPresent 为true,则 i. 让 kValue 为 ? 得到(O,Pk)。ii. 履行 ?Call(callbackfn, T, « kValue, k, O »)。d. 将 k 增加 1。
  7. 返回undefined