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

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

Где провести грань между производительностью и удобочитаемостью? Когда мы жертвуем тем или другим? Нужно ли когда-нибудь жертвовать одним из них?

Это некоторые из вопросов, на которые я хотел бы ответить или, по крайней мере, попытаться понять вместе.

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

Та же проблема, разные решения

Что ж, некоторое время назад было очень распространено увидеть что-то в этом роде для следующей проблемы:

Учитывая массив неупорядоченных чисел, верните новый массив, добавив 1 к каждому значению и отсортировав его, не изменяя исходный

var numbers = [2, 4, 12, 6, 8, 29, 5, 10, 87, 11, 7];

function process(arr) {
    let newArr = arr.slice();
    newArr[0]++;
    for (let i = 1; i < newArr.length; i++) {
        const current = newArr[i] + 1;
        let leftIndex = i - 1;

        while (leftIndex >= 0 && newArr[leftIndex] > current) {
            newArr[leftIndex + 1] = newArr[leftIndex];
            leftIndex = leftIndex - 1;
        }
        newArr[leftIndex + 1] = current;
    }
    return newArr;
}

const newArray = process(numbers);

(Я использую сортировку вставкой, потому что ее проще реализовать)

Этот образец кода на самом деле не читается, но все же он производительный, намного более производительный, чем читаемый код ES6, например, этот:

const process = (arr) => arr
    .map(num => num + 1)
    .sort((a, b) => a - b);

const newArray = process(numbers);

Фактически, первый пример кода примерно на 75% быстрее, чем второй, хотя второй пример более читабелен и даже может быть упрощен до однострочника:

const newArray = numbers.map(num => num + 1).sort((a, b) => a - b);

Или разделите вспомогательными функциями для лучшей читаемости:

const addOne = (n) => n + 1;
const asc = (a, b) => a - b;
const newArray = numbers.map(addOne).sort(asc);

Очевидно, что образец ES6 (при любом подходе) более читабелен, что упрощает понимание кода с первого взгляда. С помощью читаемого кода мы можем быстрее знакомить новых разработчиков с проектами, мы можем легче делиться нашим кодом, и он становится более удобным в обслуживании.

Учитывая все обстоятельства, в большинстве случаев производительность становится необязательной. Вот почему ES6 так эволюционировал.

Окончательное сравнение обоих подходов:

На этом этапе вы, вероятно, спросите себя: «Что еще менее эффективно, но более читабельно?»

Что ж, давайте вместе рассмотрим некоторые из основных сценариев использования.

Синтаксис распространения против Object.assign ()

Возьмем следующую простую задачу:

Скопируйте объект и добавьте к копии новое свойство

Решения:

const params = {...}; // filled Object

// ES6 - Spread syntax
var copy1 = { a: 2, ...params };

// Object.assign()
var copy2 = Object.assign({}, { a: 2 }, params);

Оба этих подхода делают свою работу, но мы все можем согласиться с тем, что синтаксис распространения более читабелен, хотя он на ~ 54% медленнее.

Для цикла против уменьшения

Проблема:

Суммируйте все значения массива

Решения. Начнем с классического цикла for…:

const numbers = [2, 4, 12, 6, 8, 29, 5, 10, 87, 11, 7];

function arraySum(arr) {
    let sum = 0;
    for (let i = 0; i < arr.length; i++) {
        sum += arr[i]
    }
    return sum;
}

const sumOfNumbers = arraySum(numbers);

А теперь приступим к самому могущественному reduce:

const numbers = [2, 4, 12, 6, 8, 29, 5, 10, 87, 11, 7];

const add = (a, b) => a + b;
const arraySum = (arr) => arr.reduce(add);

const sumOfNumbers = arraySum(numbers);

В этом случае reduce чрезвычайно дорого с точки зрения производительности, на ~ 96% медленнее!

Для vs while vs do while

Разница почти незаметна, но, тем не менее, в случае сомнений… Воспользуйтесь классическим циклом for.

Когда что использовать?

Ух ты! Теперь это хит ... Я использую синтаксис распространения, сокращение и т. Д. Для всех своих операций!

Настроение тут вроде бы удручающее, нам обещали читабельность без затрат на производительность! Я хочу свои деньги обратно! (режим паники)

Не будем паниковать и проанализируем ситуацию. Итак, «Когда что использовать?»

Ответить на поставленный выше вопрос проще, чем ожидалось: Зависит.

Возвращаясь к первому примеру, если нам нужно: скопировать, добавить и отсортировать массив или объект малого или среднего размера… Затем мы перейдем к удобочитаемости, мы будем использовать все доступные игрушки в арсенале ES6.

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

Попробуем внести это в списки.

Когда отдавать предпочтение удобочитаемости

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

Когда отдавать предпочтение производительности

  • При работе с большими данными
  • Когда приложение работает медленно или возникают другие проблемы с производительностью
  • Когда проект должен быть масштабируемым
  • При работе в личном проекте пишите как хотите

Итак, если мы имеем дело с большими данными, избегайте использования синтаксиса сокращения, фильтрации, сопоставления, распространения и т. Д. В той части кода, которая конкретно имеет дело с этим объектом или массивом.

Выводы

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

Несомненно, новые функции ES6 являются благословением и делают ежедневное кодирование с помощью JavaScript удовольствием, но если мы боремся с производительностью, если мы обрабатываем большие объемы данных ... Мы должны пересмотреть, какие инструменты мы используем.

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

Для больших объемов данных я исследую и внедряю наиболее эффективные алгоритмы для решения этой задачи. 💪 👓

В остальном я предпочитаю читаемую красоту ES6! ❤

Отказ от ответственности

Результаты тестирования, представленные в этом сообщении, могут незначительно отличаться в зависимости от рабочей нагрузки браузера, ОС и сервера.

📝 Прочтите этот рассказ позже в Журнале.

🗞 Просыпайтесь каждое воскресное утро и слышите самые интересные истории, мнения и новости недели, ожидающие в вашем почтовом ящике: Получите примечательный информационный бюллетень›