Согласно текущей документации MDN, существует 438 задокументированных методов JavaScript. Поскольку JavaScript является языком в Интернете, я полон решимости овладеть им или, по крайней мере, стараться не отставать.

Если вы хоть немного знакомы с JavaScript, то, вероятно, знакомы с более известными методами JavaScript - map (), filter (), циклом for… in и, если вам когда-либо приходилось добавлять элементы в массив , уменьшать().

Я признаю, что reduce () всегда немного сбивал меня с толку. Прежде всего, он принимает функцию обратного вызова (ставит в очередь немного неудобное, почти паническое чувство), и у него есть некоторые необязательные аргументы, которые могут радикально изменить то, что возвращает метод. Но, немного поигравшись с ним в консоли, я наконец понял некоторые его нюансы.

Итак, давайте углубимся и исследуем, ладно?

Как использовать reduce () для добавления элементов в массив

Как я упоминал выше, наиболее частое использование (я предполагаю) метода reduce () - это добавление элементов в массив, поэтому мы сначала рассмотрим это.

Допустим, я ребенок с банкой, полной монет, и коплю деньги, чтобы купить новую коробку мелков (ИМХО, лучшая вещь на свете).

монеты = [1, 5, 1, 5, 1, 10, 25, 10, 25, 1, 1, 5, 10, 10, 5, 5, 1]

Чтобы добавить все эти монеты, мы воспользуемся функцией reduce (). Reduce () принимает пару аргументов - ужасную функцию обратного вызова и начальное значение. (Аргумент начального значения не является обязательным, и мы рассмотрим это чуть позже). Однако функция обратного вызова не должна пугать - на самом деле это довольно круто.

Вот как это выглядит…

Coins.reduce ((аккумулятор, currentElement) = ›{}, initialValue)

Обратите внимание, что сама функция обратного вызова принимает два аргумента - аккумулятор и currentElement. Важно понимать, что reduce () - это метод цикла: он выполняется один раз для каждого элемента в вашем массиве. аккумулятор - это значение, возвращаемое при каждом запуске метода reduce (). currentElement - это, как вы уже догадались, элемент, рассматриваемый в данный момент во время выполнения цикла. Если задано initialValue, тогда наш аккумулятор будет установлен в initialValue при первом прохождении цикла, и наш цикл начнется с первого элемента в массиве. Итак, заполнение нашего метода reduce () для добавления наших монет будет выглядеть так ...

coin.reduce ((аккумулятор, currentElement) = ›{return аккумулятор + currentElement}, 0);

Запуск этого в вашей консоли должен вернуть 121. Итак, у нас есть 121 цент, чтобы потратить на нашу покупку мелка. Да!

Вот подробное описание того, что происходит, когда движок JavaScript работает…

На нашей первой итерации, поскольку мы присвоили initialValue (0), наш аккумулятор равен 0, а наш currentElement является первым элементом в нашем массиве, 1.

coin.reduce ((аккумулятор (0), currentElement (1)) = ›{аккумулятор возврата (0) + currentElement (1)}, 0);

Значение, возвращаемое на нашей первой итерации, равно 1 (0 + 1), а на нашей второй итерации аккумулятор сбрасывается до 1.

coin.reduce ((аккумулятор (1), currentElement (5)) = ›{аккумулятор возврата (1) + currentElement (5)}, 0);

Теперь возвращается значение 6 (1 + 5), и наш аккумулятор снова сбрасывается.

Обратите внимание, что аккумулятор продолжает сбрасываться (или накапливаться, а?) На каждой итерации цикла. Это продолжается до тех пор, пока наш цикл не завершится с последним элементом в нашем массиве, когда он выдаст окончательное значение, 121.

Как все меняется, если мы опускаем начальное значение

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

coin.reduce ((аккумулятор, currentElement) = ›{return аккумулятор + currentElement});

Хм ... запуск этого в консоли возвращает то же самое значение - 121. Важно помнить, что даже если мы получаем то же возвращаемое значение, опуская начальное значение, это упущение полностью меняет способ запуска метода reduce () .

Из документации MDN -

Если initialValue не указан, то accumulator будет равно первому значению в массиве, а currentValue(Element) будет равно второму.

* Небольшое примечание - я предпочитаю использовать имя переменной currentElement (вместо currentValue) - это просто делает процесс более понятным для меня.

Для нашего массива монет это означает, что на первой итерации метода reduce () наш аккумулятор равен 1 (первое значение в нашем массиве), а наш currentElement равен 5 (второе значение в нашем массиве).

монеты = [1, 5, 1, 5, 1, 10, 25, 10, 25, 1, 1, 5, 10, 10, 5, 5, 1]

coin.reduce ((аккумулятор (1), currentElement (5)) = ›{аккумулятор возврата (1) + currentElement (5)});

Это может показаться довольно простым, но если вы не помните, что метод reduce () имеет такое уникальное поведение, вы можете получить неожиданные результаты при попытке использовать его в будущем.

Другие аргументы для функции обратного вызова reduce ()

Помимо аккумулятора и currentElement (которые не являются необязательными), reduce () также принимает два других (необязательных) аргумента - currentIndex и array. currentIndex, как вы догадались, представляет собой индекс currentElement, а array - это просто массив, для которого вызывается метод reduce ().

Допустим, у меня есть массив чисел (числа = [1, 2, 3, 4, 5, 6]), и я хочу добавить все остальные числа в этот массив, начиная с первого элемента. Для этого я могу использовать необязательный аргумент currentIndex!

В этой функции обратного вызова для уменьшения () у меня есть условие, которое проверяет currentIndex - если currentIndex четный (я использую оператор по модулю для проверки остатка), то я добавлю этот элемент в аккумулятор. . Если currentIndex не четный, то я не буду добавлять текущий элемент, а просто верну аккумулятор в том виде, в котором он сейчас стоит.

Выполнение этого в консоли должно вернуть 9 - результат сложения 1, 3 и 5 (с индексами 0, 2 и 4 соответственно).

Ставка на неправильную ногу

Теперь давайте попробуем сложить другие числа (с индексами 1, 3 и 5).

Обратите внимание, что единственное изменение, которое я сделал здесь, относится к нашему условному выражению (вместо currentIndex% 2 === 0 это currentIndex% 2! == 0).

Запуск этого в консоли возвращает 13. Эй! Что дает?! 2 + 4 + 6 = 12, а не 13.

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

Наш метод reduce () говорит: «Эй! Вы не указали мне начальную стоимость! Я думаю, это означает, что вы хотите, чтобы первый элемент в массиве начинался как значение аккумулятора, а второй элемент начинался как currentElement? Хорошо, конечно! »Наша первая итерация метода reduce () теперь выглядит так ...

числа = [1, 2, 3, 4, 5, 6]

В этом примере я вставил значения из нашего массива чисел в соответствии с правилами метода reduce (). Наш аккумулятор установлен на первый элемент в нашем массиве (1), наш currentElement установлен на второй элемент в нашем массиве (2), а currentIndex установлен на индекс currentElement (индекс 2 равен 1). Наши условные проверки, чтобы увидеть, является ли наш currentIndex (1) четным - это не так - и поэтому наш аккумулятор (1) добавляется к нашему currentElement (2) (1 + 2 = 3), а на второй итерации нашего сокращения ( ), наш аккумулятор установлен на 3. Очевидно, что это не то, что мы хотим, так как же это исправить?

Добавляем начальное значение!

Запуск этого в консоли сейчас должен дать ожидаемый результат - 12! Ура!

Другие действия, которые вы можете сделать с помощью reduce (), кроме сложения (подсказка… вы тоже можете вычесть)

Чтобы у меня не создалось впечатление, что reduce () на самом деле полезен только для добавления вещей, давайте еще немного рассмотрим reduce ().

Возвращаясь к нашей истории о том, что я ребенок покупаю мелки, скажем, что я делаю покупки и хочу купить коробку с 64 счетчиками примерно за 4,23 доллара или 423 цента. * Однако покупать эту коробку не собираюсь -

Хорошо, я собираюсь купить коробку по разумной цене (4,23 доллара). На самом деле я хочу знать не то, сколько денег я скопил, а сколько еще мне нужно, чтобы купить свои мелки. Для этого я могу использовать reduce () ...

Здесь я устанавливаю начальное значение 423 и с каждой итерацией вычитаю свои монеты. Довольно подлый!

Это возвращает 302 цента или 3,02 доллара. Идеально! Пора еще раз обыскать диванные подушки ...

В заключение…

Вы действительно можете сделать гораздо больше с помощью метода reduce () (подсказка ... он выходит далеко за рамки добавления и вычитания), но драма нашей истории с карандашами была довольно утомительной психологически и эмоционально, поэтому я обращусь к ним в своей следующий блог - Изучение метода reduce () в JavaScript (часть 2). До скорого…