Разбираем JavaScript код: 7 проблем, ухудшающих читабельность
В этой статье мы расскажем о семи проблемах, исправив которые вы сможете сделать свой 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-коде, которые можно упростить. Используйте эти рекомендации с осторожностью.