Оглавление
JavaScript
Магические числа
Не используйте магические числа. Выносите все значения в именованные константы, имя которых позволяет понять предназначение этого числа или то, откуда оно взялось.
/* 💩 Плохо: не понятно через сколько выполнится функция */
setTimeout(callback, 86400000)
/* 😊 Хорошо: понятно что такое 86400000 */
const MILLISECONDS_IN_DAY = 86400000
setTimeout(callback, MILLISECONDS_IN_DAY)
reduce()
Старайтесь как можно реже использовать reduce, так как это затрудняет понимание кода. Зачастую такой код можно переписать на более элегантное решение.
/* 💩 Плохо: тяжело читается */
const newArr = oldArr.reduce((acc, item) => {
if (item % 2 === 0) {
return acc
}
var newItem = item * 2
acc.push(newItem)
return acc
}, [])
/* 😊 Хорошо: переписали на более читабельные filter и map */
const newArr = oldArr
.filter((item) => {
return item % 2 !== 0
})
.map((item) => {
return item * 2
})
Функции
- Создавайте функции, которые решают только одну задачу.
- Обращайте внимание на цикломатическую сложность ваших функций. Большое число указывает на то, что у функции есть много вариантов выполнения, а значит такая функция сложна для чтения и понимания.
- Делайте большинство функций чистыми — такими, которые получают все необходимые данные через свои аргументы (то есть, они не берут никаких данных из глобальных переменных) и которые только возвращают результат (и никак не влияют на внешнее состояние). Такие функции, как правило, более просты и понятны и их легче тестировать.
/* 💩 Плохо: функция зависит от сторонних значений, результат может быть всегда разный */
function multiplier(number) {
return number * window.multiplier
}
/* 😊 Хорошо: функция чистая, результат всегда предсказуем */
function double(number) {
return number * 2
}
Безымянный экспорт
Именуйте ваши экспорты. Это поможет дебажить код в DevTools, так как будет отображаться конкретное имя вместо anonymous.
/* 💩 Плохо: у функции нет имени */
export default function () {}
export default () => {}
/* 😊 Хорошо: функции с именем */
export default function foo() {}
const foo = () => {}
export default foo
Приведение строки к числу
При преобразовании строк в целые числа parseInt имеет небольшое преимущество в производительности по сравнению с Number, но Number более семантичен и читаем. Если используете parseInt – не забывайте про второй аргумент (система счисления). Избегайте использования унарного оператора +.
/* 💩 Плохо: нет второго аргумента – потенциальный баг */
parseInt('123')
/* 💩 Плохо: неявное приведение типа */
+'123'
/* 😊 Хорошо: читаемый Number */
Number('123')
/* 😊 Хорошо: правильный parseInt */
parseInt('123', 10)
Явная проверка длины
Следует избегать неявного приведения типов и стремиться к более строгому и типизированному коду. Явное всегда лучше неявного.
<template>
<--! 💩 Плохо: неявное приведение длины к false -->
<div v-if="foo.length">Vue</div>
</template>
<template>
<--! 😊 Хорошо: более читаемый вариант -->
<div v-if="foo.length > 0">Vue</div>
</template>
Живые коллекции
Перед тем как использовать методы массива на живой коллекции, её следует привести к массиву через Array.from, вместо того, чтобы использовать паттерн "одалживание метода".
const collection = document.querySelectorAll('div')
/**
* 💩 Плохо: тяжело читать, нужно знать тонкости работы
*/
let products = [].filter.call(collection, (el) => el.dataset.productId)
/**
* 😊 Хорошо: всем знакомый метод преобразования в массив
*/
let products = Array.from(collection).filter((el) => el.dataset.productId)