Методы обхода массива

Roman Ponomarev
devSchacht
Published in
4 min readApr 20, 2017

Перевод заметки Jordan Harband: Array iteration methods summarized. Опубликовано с разрешения автора.

В попытке объяснить метод reduce массивов JavaScript, я придумал следующее. Надеюсь, это будет полезно; буду счастлив вносить правки, если у кого-нибудь найдутся предложения.

Вступление

Массивы JavaScript в своем прототипе имеют много встроенных методов. Некоторые из них мутируют, то есть изменяют, базовый массив. К счастью, большинство из них этого не делают: вместо этого они возвращают совершенно новый массив. Поскольку массивы концептуально являются непрерывным списком элементов, это положительно влияет на понимание кода и удобство его обслуживания «функциональным» способом. (Я также настаиваю на том, чтобы ссылаться на массив как на «список». В некоторых языках List - родной тип данных, в этой статье, как и в JS, я отсылаю к этой концепции. Всюду, где я использую слово «список», вы можете быть уверены, что я говорю о массиве JS.) Выполнение одиночной операции над списком в целом («атомарно») и возврат нового списка упрощает способ мышления в категориях старый и новый списки, понимание их содержания и произошедших изменений во время операции.

Ниже перечислены некоторые из методов, выполняющих итерацию, они обрабатывают весь список по одному элементу за раз. Когда вы вызываете их, вы предоставляете функцию обратного вызова — единственную функцию, расчитывающую работать с одним элементом за один раз. В завимимости от используемого метода Array, функция обратного вызова получает аргументы и, как ожидается, возвращает значение (за исключением forEach), которое определяет окончательное возвращаемое значение операции обхода массива. Хотя большинство методов гарантированно выполняются для каждого элемента массива, некоторые из методов могут прекратить итерацию на полпути (когда это возможно, рассказывается ниже).

Все методы массива выполняют итерацию, как традиционно называют, «слева направо». Более точно (и менее этноцентрично): от индекса 0 до индекса length - 1 - также это называется от «начала» до «конца». reduceRight - исключение, потому что он выполняет итерацию в обратном порядке - от конца к началу.

forEach:

  • функция обратного вызова отвечает: вот элемент, сделай с ним что-нибудь сумасшедшее, мне все равно что
  • функция обратного вызова принимает следующие аргументы: item, index, list
  • итоговое возвращаемое значение: ничего — другими словами, undefined
  • пример использования:
[1, 2, 3].forEach(function (item, index) {
console.log(item, index);
});

map:

  • функция обратного вызова отвечает: вот элемент, что я должна поместить в новый список на его месте?
  • функция обратного вызова принимает следующие аргументы: item, index, list
  • итоговое возвращаемое значение: список с новыми элементами
  • пример использования:
const three = [1, 2, 3];
const doubled = three.map(function (item) {
return item * 2;
});
console.log(three === doubled, doubled); // false, [2, 4, 6]

filter:

  • функция обратного вызова — предикат — должна возвращать истинное или ложное значение
  • функция обратного вызова отвечает: должна ли я сохранить этот элемент?
  • функция обратного вызова принимает следующие аргументы: item, index, list
  • итоговое возвращаемое значение: список сохраненных элементов
  • пример использования:
const ints = [1, 2, 3];
const evens = ints.filter(function (item) {
return item % 2 === 0;
});
console.log(ints === evens, evens); // false, [2]

reduce:

  • функция обратного вызова отвечает: вот результат последней итерации, что я должна отправить в следующую итерацию?
  • функция обратного вызова принимает следующие аргументы: result, item, index, list
  • итоговое возвращаемое значение: результат последней итерации
  • пример использования:
// ПРИМЕЧАНИЕ: `reduce` и `reduceRight` принимают опциональный аргумент "initialValue" после функции обратного вызова.
// если пропустить, то по умолчанию он использует первый элемент.
const sum = [1, 2, 3].reduce(function (result, item) {
return result + item;
}, 0); // если пропустить `0`, `1` будет первым `result`, а `2` будет первым `item`

reduceRight: (тоже самое, что reduce, но в обратном порядке: от последнего к первому)

some:

  • функция обратного вызова — предикат — должна возвращать истинное или ложное значение
  • функция обратного вызова отвечает: отвечает ли этот элемент вашему требованию?
  • функция обратного вызова принимает следующие аргументы: item, index, list
  • итоговое возвращаемое значение: true после нахождения первого элемента, отвечающего вашему требованию, иначе false
  • примечание: прекращает итерацию после того, как получит истинное значение от вашей функции обратного вызова
  • пример использования:
const hasNegativeNumbers = [1, 2, 3, -1, 4].some(function (item) {
return item < 0;
});
console.log(hasNegativeNumbers); // true

every:

  • функция обратного вызова — предикат — должна возвращать истинное или ложное значение
  • функция обратного вызова отвечает: отвечает ли этот элемент вашему требованию?
  • функция обратного вызова принимает следующие аргументы: item, index, list
  • итоговое возвращаемое значение: false после нахождения первого элемента, не отвечающего вашему требованию, иначе true
  • примечание: прекращает итерацию после того, как получит ложное значение от вашей функции обратного вызова
  • пример использования:
const allPositiveNumbers = [1, 2, 3].every(function (item) {
return item > 0;
});
console.log(allPositiveNumbers); // true

find:

  • функция обратного вызова — предикат — должна возвращать истинное или ложное значение
  • функция обратного вызова отвечает: это тот элемент, который вы ищите?
  • функция обратного вызова принимает следующие аргументы: item, index, list
  • итоговое возвращаемое значение: элемент, который вы ищите, или undefined
  • примечание: прекращает итерацию после того, как получит истинное значение от вашей функции обратного вызова
  • пример использования:
const objects = [{ id: 'a' }, { id: 'b' }, { id: 'c' }];
const found = objects.find(function (item) {
return item.id === 'b';
});
console.log(found === objects[1]); // true

findIndex:

  • функция обратного вызова — предикат — должна возвращать истинное или ложное значение
  • функция обратного вызова отвечает: это тот элемент, который вы ищите?
  • функция обратного вызова принимает следующие аргументы: item, index, list
  • итоговое возвращаемое значение: индекс элемента, который вы ищите, или -1
  • примечание: прекращает итерацию после того, как получит истинное значение от вашей функции обратного вызова
  • пример использования:
const objects = [{ id: 'a' }, { id: 'b' }, { id: 'c' }];
const foundIndex = objects.findIndex(function (item) {
return item.id === 'b';
});
console.log(foundIndex === 1); // true

Слушайте наш подкаст в iTunes и SoundCloud, читайте нас на Medium, контрибьютьте на GitHub, общайтесь в группе Telegram, следите в Twitter и канале Telegram, рекомендуйте в VK и Facebook.

Статья на GitHub

--

--