Array.prototype.forEach()

Сводка

Метод forEach() выполняет указанную функцию один раз для каждого элемента в массиве.

Синтаксис

arr.forEach(callback[, thisArg])

Параметры

callback
Функция, создающая элемент нового массива, принимает три аргумента:
currentValue
Текущий обрабатываемый элемент в массиве.
index
Индекс текущего обрабатываемого элемента в массиве.
array
Массив, по которому осуществляется проход.
thisArg
Необязательный параметр. Значение, используемое в качестве this при вызове функции callback.

Описание

Метод forEach() выполняет функцию callback один раз для каждого элемента, находящегося в массиве в порядке возрастания. Она не будет вызвана для удалённых или пропущенных элементов массива. Однако, она будет вызвана для элементов, которые присутствуют в массиве и имеют значение undefined.

Функция callback будет вызвана с тремя аргументами:

  • значение элемента (value)
  • индекс элемента (index)
  • массив, по которому осуществляется проход (array)

Если в метод forEach() был передан параметр thisArg, при вызове callback он будет использоваться в качестве значения this. В противном случае, в качестве значения this будет использоваться значение undefined. В конечном итоге, значение this, наблюдаемое из функции callback, определяется согласно обычным правилам определения this, видимого из функции.

Диапазон элементов, обрабатываемых методом forEach(), устанавливается до первого вызова функции callback. Элементы, добавленные в массив после начала выполнения метода forEach(), не будут посещены функцией callback. Если существующие элементы массива изменятся, значения, переданные в функцию callback, будут значениями на тот момент времени, когда метод forEach() посетит их; удалённые элементы посещены не будут.

Примечание: Не существует способа остановить или прервать цикл forEach(). Если это требуется, можно воспользоваться методами Array.prototype.every() или Array.prototype.some(). Смотрите примеры ниже.

Метод forEach() выполняет функцию callback один раз для каждого элемента массива; в отличие от методов every() и some(), он всегда возвращает значение undefined.

Примеры

Пример: печать содержимого массива

Следующий код выводит каждый элемент массива на новой строке журнала:

function logArrayElements(element, index, array) {
  console.log('a[' + index + '] = ' + element);
}

// Обратите внимание на пропуск по индексу 2, там нет элемента, поэтому он не посещается
[2, 5, , 9].forEach(logArrayElements);
// логи:
// a[0] = 2
// a[1] = 5
// a[3] = 9

Пример: прерывание цикла

Следующий код использует Array.prototype.every() для логирования содержимого массива и останавливается при превышении значением заданного порогового значения THRESHOLD.

var THRESHOLD = 12;
var v = [5, 2, 16, 4, 3, 18, 20];
var res;

res = v.every(function(element, index, array) {
  console.log('element:', element);
  if (element >= THRESHOLD) {
    return false;
  }

  return true;
});
console.log('res:', res);
// логи:
// element: 5
// element: 2
// element: 16
// res: false

res = v.some(function(element, index, array) {
  console.log('element:', element);
  if (element >= THRESHOLD) {
    return true;
  }

  return false;
});
console.log('res:', res);
// логи:
// element: 5
// element: 2
// element: 16
// res: true

Пример: функция копирования объекта

Следующий код создаёт копию переданного объекта. Существует несколько способов создания копии объекта, и это один из них. Он позволяет понять, каким образом работает Array.prototype.forEach(), используя функции мета-свойств Object.* из ECMAScript 5.

function copy(o) {
  var copy = Object.create(Object.getPrototypeOf(o));
  var propNames = Object.getOwnPropertyNames(o);

  propNames.forEach(function(name) {
    var desc = Object.getOwnPropertyDescriptor(o, name);
    Object.defineProperty(copy, name, desc);
  });

  return copy;
}

var o1 = { a: 1, b: 2 };
var o2 = copy(o1); // теперь o2 выглядит также, как и o1

Полифилл

Метод forEach() был добавлен к стандарту ECMA-262 в 5-м издании; поэтому он может отсутствовать в других реализациях стандарта. Вы можете работать с ним, добавив следующий код в начало ваших скриптов, он позволяет использовать forEach() в реализациях, которые не поддерживают этот метод. Этот алгоритм является точно тем, что описан в ECMA-262 5-го издания; он предполагает, что Object и TypeError имеют свои первоначальные значения и что callback.call вычисляется в оригинальное значение Function.prototype.call().

// Шаги алгоритма ECMA-262, 5-е издание, 15.4.4.18
// Ссылка (en): http://es5.github.io/#x15.4.4.18
// Ссылка (ru): http://es5.javascript.ru/x15.4.html#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. Положим O равным результату вызова ToObject passing the |this| value as the argument.
    var O = Object(this);

    // 2. Положим lenValue равным результату вызова внутреннего метода Get объекта O с аргументом "length".
    // 3. Положим len равным ToUint32(lenValue).
    var len = O.length >>> 0;

    // 4. Если IsCallable(callback) равен false, выкинем исключение TypeError.
    // Смотрите: http://es5.github.com/#x9.11
    if (typeof callback !== 'function') {
        throw new TypeError(callback + ' is not a function');
    }

    // 5. Если thisArg присутствует, положим T равным thisArg; иначе положим T равным undefined.
    if (arguments.length > 1) {
      T = thisArg;
    }

    // 6. Положим k равным 0
    k = 0;

    // 7. Пока k < len, будем повторять
    while (k < len) {

      var kValue;

      // a. Положим Pk равным ToString(k).
      //   Это неявное преобразование для левостороннего операнда в операторе in
      // b. Положим kPresent равным результату вызова внутреннего метода HasProperty объекта O с аргументом Pk.
      //   Этот шаг может быть объединён с шагом c
      // c. Если kPresent равен true, то
      if (k in O) {

        // i. Положим kValue равным результату вызова внутреннего метода Get объекта O с аргументом Pk.
        kValue = O[k];

        // ii. Вызовем внутренний метод Call функции callback с объектом T в качестве значения this и
        // списком аргументов, содержащим kValue, k и O.
        callback.call(T, kValue, k, O);
      }
      // d. Увеличим k на 1.
      k++;
    }
    // 8. Вернём undefined.
  };
}

Спецификации

Спецификация Статус Комментарии
ECMAScript 5.1 (ECMA-262)
Определение 'Array.prototype.forEach' в этой спецификации.
Стандарт Изначальное определение. Реализована в JavaScript 1.6.
ECMAScript 6 (ECMA-262)
Определение 'Array.prototype.forEach' в этой спецификации.
Кандидат в рекомендации  

Совместимость с браузерами

Возможность Chrome Firefox (Gecko) Internet Explorer Opera Safari
Базовая поддержка (Да) 1.5 (1.8) 9 (Да) (Да)
Возможность Android Chrome для Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Базовая поддержка (Да) (Да) 1.0 (1.8) (Да) (Да) (Да)

Смотрите также

Метки документа и участники

Contributors to this page: Mingun, Ajooluz, teoli, dunmaksim, IgorKlopov, ipetropolsky, John Wehin
Обновлялась последний раз: Mingun,
Скрыть боковую панель