Рубрики
Без рубрики

Остерегайтесь с методами цепочки массива в JavaScript

Класс Array Balaganesh Damodaran JavaScript’s Class выставляет довольно несколько методов (фильтр, карта, уменьшение), которые ограничивают массив и вызовут функцию iTerator для выполнения действий в массиве. Сторирование этих методов позволяет вам писать чистые, легко читать код. Но что эта удобство будет стоить нам

Балаганеш Дамодаран

Класс Array JavaScript предоставляет довольно несколько методов (фильтр, карта, уменьшение), которые ограничивают массив и вызовут функцию итератора для выполнения действий в массиве. Сторирование этих методов позволяет вам писать чистые, легко читать код. Но что эта удобство будет стоить нам с точки зрения производительности, и это того стоит?

JavaScript – это «функциональный» язык. Это означает, что функции являются объектами первого класса в JavaScript, и как таковые их могут быть переданы в качестве параметров в другие функции. Существует довольно много встроенных методов, предоставляемых стандартной библиотекой JavaScript, которая использует этот факт, чтобы позволить нам писать чистые, понятные и легко читать код.

Встроенные методы массива JavaScript и Цепочка

Один такой встроенный класс, который делает широкое использование функциональной природы JavaScript, является Массив класс. Массив S в JavaScript выставляют ряд методов экземпляра, которые:

  • Принять функцию как аргумент,
  • Итерация на массиве,
  • И позвоните в функцию, проходя вдоль элемента массива в качестве параметра к функции.

Самые популярные из них, конечно, Foreach , Фильтр , карта и Уменьшить Отказ Поскольку некоторые из этих методов также возвращают Массив Экземпляр как возвращаемое значение метода, они часто встречаются друг с другом:

const tripExpenses = [{    amount: 12.07,    currency: 'USD',    paid: true}, {    amount: 1.12,    currency: 'USD',    paid: true}, {    amount: 112.00,    currency: 'INR',    paid: false}, {    amount: 54.17,    currency: 'USD',    paid: true}, {    amount: 16.50,    currency: 'USD',    paid: true}, {    amount: 189.50,    currency: 'INR',    paid: false}];
const totalPaidExpensesInINR = tripExpenses    .filter(expense => expense.paid)    .map(expense => {        if(expense.currency == 'USD')            return expense.amount * 70;        else            return expense.amount;    })    .reduce((amountA, amountB) => amountA + amountB);

В этом примере мы рассчитываем общие платные расходы после преобразования их от USD на INR. Для этого мы:

  • Фильтр ing TripexPenses извлечь только оплачиваемые расходы,
  • карта пинг стоимость суммы из указанной валюты и преобразование его в INR и
  • Уменьшить INR INR, чтобы получить сумму.

Выглядит как общий, очень типичный, действительный корпус для методов массива цепи правильно? Многие разработчики, которые учили писать функциональный JavaScript, выйдут с чем-то похожим, когда попросили решить эту проблему.

Проблема с методом массива

В настоящее время наше TripexPenses У Maray есть только 6 предметов, поэтому это относительно быстро. Но что происходит, когда мы должны проанализировать расходы на поездки, скажем, целая компания сотрудников на весь финансовый год, и наша TripexPenses Массив начинает иметь сотни тысяч элементов?

Благодаря JSPERF, мы можем визуализировать эту стоимость довольно легко. Итак, давайте запустим тест сравнения на тот же код с TripexPenses Имея 10 элементов, 10 000 элементов и 100 000 элементов. Вот результат Сравнение jsperf :

График показывает количество операций в секунду, а выше лучше. Хотя я ожидал, что 100 000 элементов случая для плохого выполнения, я действительно не ожидал, что 10 000 элементов для этого плохо выполняют это. Так как он не очень виден на графике, давайте посмотрим на цифры:

  • 10 элементов – 6,142,739 OPS в секунду
  • 10 000 элементов – 2199 OPS в секунду
  • 100 000 элементов – 223 OPS в секунду

Yikes, это действительно плохо! А при обработке массива 100 000 элементов часто не произойдут часто, 10 000 элементов – это очень правдоподобный случай, который я регулярно видел в нескольких приложениях, которые я разработал (в основном на стороне сервера).

Это показывает нам, что когда мы пишем – даже то, что кажется довольно простым кодом – мы действительно должны следить за любыми проблемами производительности, которые могут обрезать из-за того, как мы пишем наш код.

Если вместо цепочки Фильтр , карта и Уменьшить Методы вместе, мы переписываем наш код такими, что вся работа проделана встроенная, в одной петле, мы можем значительно улучшить производительность.

let totalPaidExpensesInINR = 0;
for(let expense of tripExpenses){    if(expense.paid){        if(expense.currency == 'USD')            totalPaidExpensesInINR += (expense.amount * 70);        else            totalPaidExpensesInINR += expense.amount;    }}

Давайте запустим другой Сравнение jsperf Чтобы увидеть, как это выполняет против его функционального аналога, в тесте 10 000 элементов:

Как видите, на Chrome (и устерем расширения. JS), функциональный пример представляет собой колоссы на 77% медленнее, чем для примера. На Firefox цифры намного ближе, но функциональный пример по-прежнему на 16% медленнее, чем для примера.

Почему такая большая производительность дельты?

Так почему же функциональный пример намного медленнее, чем в примере? Ну, это сочетание факторов, но основные факторы, которые, как разработчик, мы можем контролировать от земли пользователя:

  • Зацикливаться на одних и тех же элементах массива несколько раз.
  • Накладные расходы функций требуют для каждой итерации в функциональном примере.

Если вы увидите например, вы увидите, что мы когда-либо повторяемся через TripexPense массив один раз. Также мы не называем функции изнутри, вместо этого выполняем наши расчеты встроенные.

Одной из крупных «выигрывает», что современные двигатели JavaScript получают вкладывающих функциональных вызовов. Это означает, что двигатель на самом деле будет компилировать ваш код в версию, где компилятор заменяет вызов функции с самой функцией (I.E. Inline, где вы вызываете функцию). Это устраняет накладные расходы на вызов функции и обеспечивает огромные успехи производительности.

Тем не менее, мы не всегда не можем сказать, наверняка, будет ли двигатель JavaScript выбрать встроенную функцию или нет, поэтому делает это сами, гарантируют, что у нас есть наилучшие возможные показатели.

Заключение

Некоторые разработчики могут рассмотреть вопрос о примере менее читаемой и сложнее понять, чем функциональный пример. Для этого конкретного примера я бы сказал, что оба стиля одинаково читаются. Однако в случае функционального примера удобство цепочки способа имеет тенденцию скрывать множественные итерации и вызовы функций от разработчика, что позволяет легко сделать неопытный разработчик для записи нефинансирующего кода.

Я не говорю, что вы всегда должны избегать функционального способа – я уверен, что есть много действительных случаев для использования функционального способа и для цепочки методов. Но общее правило, чтобы помнить, когда речь идет о производительности и итерационных массивах в JavaScript, это то, что если вы цепляетесь методами, которые ограничиваются всеми массивами, вы, вероятно, должны остановиться и рассмотреть влияние на производительность, прежде чем идти вперед.

Я хотел бы услышать ваше мнение о том, что я написал в этой статье. Сделать Chime с вашими комментариями ниже.

[6 февраля 2019 года] Некоторые предостережения, и вещи, которые должны иметь в виду, как указано комментаторами

Как указал по Пол Б, При использовании `для … для использования в браузерах. Однако, как говорит Павел, есть довольно много преимуществ для прилипания функции итератора. Пойди прочитайте Его комментарий, Это достойно стать статьи все само собой.

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

Первоначально опубликовано asleepysamurai.com 8 января 2019 года.

Оригинал: “https://www.freecodecamp.org/news/beware-of-chaining-array-methods-in-javascript-ef3983b60fbc/”