Array.prototype.forEach()

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

Синтаксис

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

Параметри

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

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

Вертає

undefined.

Опис

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

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

  1. значення елемента;
  2. індекс елемента;
  3. масив, що перебирається.

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

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

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

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

Заувага: Зупинити чи перервати цикл forEach() неможливо без викидання винятку. Якщо вам це потрібно, метод forEach() — не ліпший вибір. 

Завчасне переривання може бути виконане за допомогою:

Методи масивів: every(), some(), find() та findIndex() перевіряють елементи масиву функцією-предикатом, яка повертає правдиве значення, якщо наступна ітерація необхідна.

Приклади

Операція не виконується для неініціалізованих значень (розріджені масиви)

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
// коментар: як бачите, пропущене значення між 3 та 7 не викликало функцію.

Перетворення циклу for на forEach

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

// було
for (let i = 0; i < items.length; i++) {
  copy.push(items[i])
}

// стане
items.forEach(function(item) {
  copy.push(item)
});

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

Заувага: Для того, щоб відобразити вміст масиву у консолі, ви можете скористатись методом console.table(), який виведе відформатовану версію масиву. Наступний приклад ілюструє інший спосіб це зробити, за допомогою forEach().

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

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.

Якщо передавати аргумент функції за допомогою стрілкового запису функції, то параметр 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();
  }
});

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

Вирівнювання масиву

Даний приклад наведено суто для навчальння. Якщо вам потрібно вирівняти масив вбудованими методами, ви можете скористатись методом Array.prototype.flat() (очікується у ES2019 та вже реалізований у деяких переглядачах).

/**
* Вирівнює переданий масив у одномірний
*
* @params {array} arr
* @returns {array}
*/
function flatten(arr) {
  const result = [];

  arr.forEach((i) => {
    if (Array.isArray(i)) {
      result.push(...flatten(i))
    } else {
      result.push(i)
    }
  });

  return result;
}

// Використання
const problem = [1, 2, 3, [4, 5, [6, 7], 8, 9]]

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

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

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

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

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
forEachChrome Full support YesEdge Full support 12Firefox Full support 1.5IE Full support 9Opera Full support YesSafari Full support YesWebView Android Full support YesChrome Android Full support YesFirefox Android Full support 4Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support Yesnodejs Full support Yes

Legend

Full support  
Full support

Див. також