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

var arr = ['a', 'b', 'c'];

arr.forEach(function(element) {
    console.log(element);
});

// a
// b
// c

Синтаксис

arr.forEach(function callback(currentValue, index, array) { … }[, thisArg]);

Параметри

callback
Функція, що виконується для кожного елемента. Приймає три аргументи:
currentValue
Значення чергового елемента масиву.
index
Індекс чергового елемента в масиві.
array
Масив, до якого застосовано forEach().
thisArg Optional

Значення, що використовується як this коли викликається callback.

Вертає

undefined.

Опис

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

Функція callback викликається з трьома аргументами:

  • значення елемента
  • індекс елемента
  • масив, що перебирається

Якщо для forEach() вказано параметр thisArg, його буде використано як this для функції callback. Якщо ж не вказано, то буде використано значення undefined. Зрештою значення this для функції callback визначатиметься відповідно до загальних правил.

Множина індексів елементів, що їх перебиратиме forEach() з'ясовується ще до першого виклику callback. Елементи, додані після здійснення виклику forEach(), буде знехтувано (callback для жодного з них не викликатиметься). Якщо змінити значення котрогось зі ще не відвіданих елементів масиву, зміни буде враховано — до функції callback потрапить те значення елемента, яке він мав безпосередньо перед відповідним викликом callback. Якщо елемент видалено до відвідування, його відвідано не буде. Якщо вже відвіданий елемент видалено упродовж перебирання (наприклад, за допомогою shift()), індекси подальших елементів зменшаться на одиницю, а отже певний елемент буде пропущено — дивіться приклади нижче у статті.

На відміну від map() чи reduce(), метод forEach() завжди вертає значення undefined, тож продовжити ланцюжок викликів після нього неможливо. Досить типовим є виклик forEach() наприкінці ланцюжка методів з метою виконання додаткових дій.

Сам метод forEach() не змінює масив, на якому його викликано, втім усередині функції callback це можливо.

Заувага: Зупинити чи перервати цикл forEach() неможливо без викидання винятку. Якщо вам це потрібно, метод forEach() — не ліпший вибір. Скористайтеся натомість звичайним циклом. Якщо ви перевіряєте елементи масиву на відповідність певній умові та маєте потребу повернути значення типу Boolean, зверніть увагу на методи every() та some(). Також можна скористатись новими методами find() та findIndex(), якщо вони доступні, — в цих методах перебір елементів переривається, якщо чергове значення відповідає умові.

Приклади

Перехід від for до forEach

Було:

const items = ['щось', 'то', 'має', 'бути'];
const copy = [];

for (let i = 0; i < items.length; i++) {
  copy.push(items[i])
}

Стане:

const items = ['щось', 'то', 'має', 'бути'];
const copy = [];

items.forEach(function(item) {
  copy.push(item)
});

Друкування вмісту масиву

Наведений код виводить у консоль індекс та значення кожного елемента масиву:

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

// Завважте, що індекс 2 буде пропущено,
// позаяк елемента на тому місці в масиві немає.
[2, 5, , 9].forEach(logArrayElements);

// Буде виведено у консоль:
// array[0] = 2
// array[1] = 5
// array[3] = 9

Використання thisArg

Наведений приклад змінює властивості об'єкта відповідно до кожного елемента в отриманому масиві:

function Counter() {
  this.sum = 0;
  this.count = 0;
}

Counter.prototype.add = function(array) {
  array.forEach(function(entry) {
    this.sum += entry;
    this.count++;
  }, this);
  // ^---- Зверніть увагу!
};

const obj = new Counter();

obj.add([2, 5, 9]);

obj.count;  // 3 
obj.sum;    // 16

Оскільки для forEach() вказано параметр thisArg, для кожного виклику callback (тут безіменної функції) він вживатиметься як this.

Заувага: Якщо передавати перший аргумент forEach() за допомогою стрілкового запису функції, то параметр thisArg можна не вказувати, позаяк стрілкова функція сама захоплює значення this.

Функція копіювання об'єкта

Існує чимало способів створення копії об'єкта. Наведений приклад є лише одним з них і насправді призначений лише для наочного пояснення того, як працює Array.prototype.forEach() на прикладі використання нових функцій ECMAScript 5 з Object.* для роботи з керованими властивостями:

function copy(obj) {
  const copy = Object.create(Object.getPrototypeOf(obj));
  const propNames = Object.getOwnPropertyNames(obj);

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

  return copy;
}

const obj1 = {a: 1, b: 2};
const obj2 = copy(obj1);  // obj2 тепер схожий на obj1

Якщо масив змінено під час перебору, деякі елементи може бути пропущено

Наведений приклад виводить у консоль послідовно "перший", "другий" та "четвертий". Коли перебір сягне другого елемента (що має значення "другий"), виклик words.shift() видалить перший елемент масиву, а всі, що лишаться, посунуться на одне місце ліворуч — "четвертий" стане наступним (після поточного) і "третій" таким чином буде пропущено:

var words = ['перший', 'другий', 'третій', 'четвертий'];

words.forEach(function(word) {
  console.log(word);

  if (word === 'другий') {
    words.shift();
  }
});

// перший
// другий
// четвертий

Метод forEach() не створює копії масиву перед перебором, а лише з'ясовує множину індексів, що їх буде перебрано.

Запасний варіант (поліфіл)

Цей метод було стандартизовано 5-им випуском ECMA-262. Для рушіїв, що не мають підтримки цього метода, стане в нагоді наведене нижче рішення. Цей алгоритм точнісінько відповідає вимогам 5-го випуску ECMA-262 за умови, що Object і TypeError не було змінено, а виклик callback.call() відповідає очікуваному 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 = arguments[1];
    }

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

    // 7. Repeat while k < len.
    while (k < len) {

      var kValue;

      // a. Let Pk be ToString(k).
      //    This is implicit for LHS operands of the in operator.
      // b. Let kPresent be the result of calling the HasProperty
      //    internal method of O with argument Pk.
      //    This step can be combined with c.
      // c. If kPresent is true, then
      if (k in O) {

        // i. Let kValue be the result of calling the Get internal
        // method of O with argument Pk.
        kValue = O[k];

        // ii. Call the Call internal method of callback with T as
        // the this value and argument list containing kValue, k, and O.
        callback.call(T, kValue, k, O);
      }
      // d. Increase k by 1.
      k++;
    }
    // 8. return undefined.
  };
}

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

Специфікація Статус Коментар
ECMAScript 5.1 (ECMA-262)
The definition of 'Array.prototype.forEach' in that specification.
Standard Початкова виознака. Запроваджено у JavaScript 1.6.
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Array.prototype.forEach' in that specification.
Standard  
ECMAScript Latest Draft (ECMA-262)
The definition of 'Array.prototype.forEach' in that specification.
Living Standard  

Підтримка веб-переглядачами

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support Yes Yes1.59 Yes Yes
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidIE mobileOpera AndroidiOS Safari
Basic support Yes Yes Yes4 Yes Yes Yes

Див. також

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

 Зробили внесок у цю сторінку: asmforce, f0rza, topvova, DariaManko
 Востаннє оновлена: asmforce,