Оглавление

    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)