Разбираем JavaScript код: 7 проблем, ухудшающих читабельность

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

JavaScript код Перевод статьи Learn to spot red flags in your React/JavaScript code.

Ищите let

Еще в дни ES5 единственной возможностью для создания переменных был var. ES6 ввел такие ключевые слова как let и const.

Исходя из своего опыта, я знаю только пару ситуаций, где вам пригодится let. Конечно, он имеет место быть (как счетчик, например), но для большинства случаев const подойдет лучше. Скоро вы поймёте, почему.

Рассмотрим следующий JavaScript код. amount отображается в красном цвете, если значение отрицательно, в другом случае amount отображается в чёрном цвете.

let color;
if (amount < 0) {
  color = 'red';
} else {
  color = 'black';
}
return (
  <span style={{ color }}>
    {formatCurrency(amount)}
  </span>
);

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

const color = amount < 0 ? 'red' : 'black';

Как результат, мы сократили количество строк кода. Однако при использовании const вместо let наш компилятор выдаст ошибку, если мы случайно переназначим const где-то еще в коде.

Вот пример выходных данных от ESLint, когда я пытаюсь установить цвет на null после того, как он определен:

/Users/donavon/Projects/my-project/src/index.jsx
43:5  error 'color' is constant

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

Преимущество использования const:

  • Код выглядит понятнее.

Деконструкция – ваш друг

Синтаксис деконструкции – это выражение JavaScript, которое позволяет распаковать значения из массивов или свойств объектов в различные переменные.

Это также значительно облегчает чтение кода. Возьмем, например, этот фрагмент:

render() {
  return(
    <div className={this.props.className}>
      {
        this.props.isLoading
          ? 'Loading...'
          : this.props.children
      }
    </div>
  );
}

Есть несколько работающих операций this.props. Это медленно (да, незначительно, но всё же, несколько поисков свойства объекта должно произойти), и опять же это добавляет визуальный беспорядок.

render() {
  const { className, isLoading, children } = this.props;
  return(
    <div className={className}>
      {isLoading ? 'Loading...' : children}
    </div>
  );
}

При добавлении всего одной строки кода остальная часть становится более понятной.

Преимущества деконструкции:

  • Более быстрое выполнение.
  • Более чистый код.
  • Менее подвержена скрытым ошибкам, вызванными опечатками.

Spread вместо Object.assign

Раньше Object.assign использовали для создания копии объекта или для создания объекта из других объектов. Но сегодня с помощью babel мы можем использовать новый синтаксис ES.

Вот код, в котором используется Object.assign:

const defaults = { foo: 'foo', bar: 'bar' };
const obj1 = Object.assign({}, defaults, { bar: 'baz' });
// {foo:'foo', bar:'baz'}

Приведенный ниже код выводит те же результаты, но с использованием синтаксиса ES:

const defaults = { foo: 'foo', bar: 'bar' };
const obj1 = { ...defaults, bar: 'baz' };
// {foo:'foo', bar:'baz'}

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

У Акселя Раушмайера в статье есть четкое объяснение противостояния spread и Object.assign. Стоит прочесть, если вы действительно хотите в этом разобраться.

Преимущества использования spread:

  • Более аккуратный.
  • Потенциально более эффективный.

Использование тернарного оператора вместо логического ‘И’

Для простых if условий тернарный оператор — не лучшая вещь. Автор детально объясняет это в своей статье о тернарных операторах и логических ‘и’.

Преимущества использования:

  • Меньше “мусора” в коде.

Стрелочные функции

Стрелочные функции идеальны для написания простых компонентов (SFC) в React. Существует два вида. Первый выглядит так:

const SomeFunction = () => {
  return 'value';
};

Второй вид подразумевает наличие оператора return:

const SomeFunction = () => 'value';

Некоторые люди ошибочно называют это выражение “однострочным”, однако, как вы можете увидеть ниже, оно может охватывать несколько строк. Обратите внимание, что я использую круглые, а не фигурные скобки.

const SomeFunction = () => (
  'value'
);

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

К счастью, ESLint сможет прийти на помощь.

/Users/donavon/Projects/my-project/src/index.jsx
  12:17  error Unexpected block statement surrounding arrow body;
         move the returned value immediately after the `=>`

Единственное, что нужно помнить, это то, что для возврата объекта в выражение вы должны заключить литерал объекта в круглые скобки:

const SomeFunction = () => ({
  foo: 'foo',
  bar: 'bar',
});

Преимущество стрелочных функций:

  • Меньше “мусора” в коде.

DRY: Не повторяйте себя

Посмотрите на эти два простых компонента:

const Foo = () => (
  <div>
    <h2 className="sectionTitle">
      Foo Title
    </h2>
    ...
  </div>
);
const Bar = () => (
  <div>
    <h2 className="sectionTitle">
      Bar Title
    </h2>
    ...
  </div>
);

Заметьте, что выделенные разделы кода в функциях Foo и Bar почти идентичны. Очевидно, что они оба отображают название в определённом стиле. Что делать, если у вас будет точно такой же код в 4, 5 и более местах? Вероятно, любые изменения в этом фрагменте кода, сделанные в будущем, потребуют изменения и остальных идентичных фрагментов.

Вы должны реорганизовать дублирующийся код в одну функцию. Это называется DRY: Don’t Repeat Yourself.

const Title = text => (
  <h2 className="sectionTitle">
    {text}
  </h2>
);
const Foo = () => (
  <div>
    <Title text="Foo Title" />
    ...
  </div>
);
const Bar = () => (
  <div>
    <Title text="Bar Title" />
    ...
  </div>
);

Преимущества “DRY” кода:

  • Чистый код.
  • Легко поддерживаемый и изменяемый.

JavaScript код и constructor

Много раз при написании компонента класса React вы создаёте конструктор для установки начального значения состояния. Пример:

constructor(props) {
  super(props);
  this.state = { count: 0 };
}

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

state = { count: 0 };

Вы можете прочитать об этом больше в статье автора.

Преимущество отсутствия конструктора в коде:

  • JavaScript код становится чище.

Заключение

Умение избегать некоторые из приведённых шаблонов может сделать ваш JavaScript код проще, чище и читабельнее.

Это не жёсткие установки, которые обязан соблюдать каждый, а общие рекомендации, направленные на то, чтобы вы видели те места в вашем JS-коде, которые можно упростить. Используйте эти рекомендации с осторожностью.

Другие материалы по теме:

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ