Гарантируется ли foreach цикл в одном и том же порядке каждый раз для одного и того же набора данных? - PullRequest
0 голосов
/ 29 ноября 2018

Гарантируется ли foreach (Array.prototype.forEach) зацикливание в одном и том же порядке каждый раз для одного и того же набора данных?А почему?

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Да, forEach будет ожидать завершения предыдущего элемента перед обработкой следующего

//Sync methods;
[1,2,3].forEach(function(e){
    console.log(e)
});
//Output:
//1
//2
//3

Если вы используете Асинхронные методы внутри цикла, они будутвызываться по порядку, но цикл не будет ожидать обратного вызова.

//Async Methods
[1,2,3].forEach(function(e){
    someAsyncMethod(e, console.log);
});
//Output example:
//3
//1
//2

Этот ответ имеет несколько методов для использования асинхронных функций внутри foreach.

Что касается , почему , существует международный стандарт, называемый ECMAScript , которому должны соответствовать все реализации JavaScript;поведение Array.prototype.forEach() определено в этом стандарте.

Вы можете найти спецификацию и псевдокод для Array.prototype.forEach() в ECMAScript® 2018 Спецификация языка

0 голосов
/ 29 ноября 2018

Если реализация придерживается стандарта, тогда да, forEach обрабатывает массив по порядку, за исключением редких массивов, где неинициализированные значения игнорируются.forEach() описано в спецификации :

forEach вызывает callbackfn один раз для каждого элемента, присутствующего в массиве, в порядке возрастания.callbackfn вызывается только для тех элементов массива, которые действительно существуют;он не вызывается для отсутствующих элементов массива.

Он проходит по индексу, начиная с:

Пусть lenValue будет результатом вызова [[Get]]внутренний метод O с аргументом "length". Пусть k будет 0.
Повтор, а k ...
Увеличение k на 1

В массивах javascript являются объектами и имеют свойство length и целочисленные ключи, которые являются индексами.В спецификации говорится, что он начнется с k=0 и будет вызывать arr[k] в порядке возрастания для k < length.Он будет вызывать обратный вызов для всех значений, где arr имеет свойство k

Пример разреженного массива, в котором forEach игнорирует элементы, может выглядеть следующим образом:

let a  = Array(10)
a[5] = "Five"
a[9] = "Nine"
console.log(a)
// ignores initialized values:
a.forEach((item) => console.log(item))

Если вы выполняете асинхронные действия внутри обратного вызова, может показаться, что обратный вызов выполняется не по порядку, но все равно.

РЕДАКТИРОВАТЬ на основе комментария:

Вы можете с небольшим взломом передать объект в forEach, который выглядит как массив (у него есть длина и целочисленные ключи).forEach будет вызывать элементы в порядке index , а не в порядке, в котором они определены для объекта.Например:

// an object that has enough info
// for forEach to use
let o = {
    3: "three",
    2: "two",
    0: "zero",
    1: "one",

    length: 4
}

// calls in order of indexes, not order keys were defined
Array.prototype.forEach.call( o, (i) => console.log(i))
...