Отступы, пробелы и переносы

  • Для отступов используется знак табуляции;
  • При переносах в продолжении строки используется знак табуляции;
  • Запрещено одновременное использование табов и пробелов для отступов;
  • Выражения должны заканчиваться точками с запятой;
  • Для отступов ключевых слов, операторов и т. д. используется не более одного пробела;
let name = 1;
let longer_name = 2;
  • Открывающие скобки блоков кода находятся на одной строке с оператором, который их использует;
if (condition) {
    // code
}
  • В однострочных блоках кода, код отделен от открывающей и закрывающей скобки пробелом;
  • В однострочных массивах скобки не отделяются пробелами, первое значение идет непосредственно после открывающей скобки, а закрывающая скобка идет непосредственно после последнего значения массива;
  • После запятой всегда должен ставиться пробел, если запятая не в конце строки;
  • Файл должен заканчиваться пустой строкой;
  • Строка не должна заканчиваться пробелами;
  • В однострочных объектах и при деструктуризации фигурные скобки не отделяются пробелами от содержимого;
  • В объектах после объявления ключа не ставится пробел. После двоеточия, которое отделяет в объектах ключ от значения может стоять только один пробел;
let foo = {a: 1, b: 2};
const {a, b} = some_object;
  • Оператор вызова функции () не отделяется пробелами от названия функции;
  • В блоках кода первая и последняя строка не должны быть пустыми (код не отбивается от начала блока кода);
  • Перед скобками начинающими новый блок кода должен ставиться пробел;
  • В комментариях текст отбивается пробелом от начала комментария;

Строки

  • Для объявления строки используются двойные кавычки;
  • В строках, объявленных с помощью двойных кавычек запрещено использовать переносы;

Литералы

  • Массивы должны создаваться через литерал массива, а не через конструктор. Допустимое исключение - создание массива определенной длины;
  • Объекты должны создаваться через литерал объекта, а не через конструктор;
  • При создании объектов запрещено дублирование ключей;
  • При описании функций запрещено дублировать названия параметров;
  • В операторе switch запрещено дублировать условия (case);

Операторы

  • В бинарных и тернарных операторах операнды и символы оператора отделяются пробелами;

Именование

  • Запрещено объявлять переменные, имена которых совпадают с именами используемых в коде лейблов;
  • Все переменные должны быть названы в змеином регистре (snake_case);
  • Запрещено использовать имена переменных, которые используются во внешних областях видимости;
  • Запрещено называть переменные и свойства ключевыми словами JS;
  • Запрещено использовать переменные, не объявленные ранее;
  • Запрещено объявлять переменные без значения;
  • Запрещено напрямую обращаться к значению undefined. Для проверки типа рекомендуется использовать typeof. Для прямого сравнения с undefined можно использовать конструкцию void(0);

Предотвращение ошибок

  • Все точки с запятой должны быть проставлены явно, не стоит рассчитывать на автоматическую расстановку точек с запятой ASI (Automatic Semicolon Insertion);
  • Не рекомендуется использовать указатель Unicode BOM в коде, потому что код должен быть сохранен не в кодировке UTF-16, а в кодировке UTF-8, в которой нет указателя порядка бит;
  • Обязательно используются блоки кода даже если в выражении содержится одна строчка;
  • В коде нет пустых блоков кода;
  • Код работает в строгом режиме: в начале всех файлов явно прописана директива 'use strict';

Условные операторы

  • Запрещена "проверка Йоды (Yoda conditions, Yoda notation)" - в условных операторах в блоке условия при сравнении переменной или свойства со значением сначала идет переменная или свойство объекта и только потом значения, а не наоброт;
if (my_value === 1) {}
  • При сравнении двух значений используется оператор строгого сравнения вместо оператора нестрогого сравнения;
  • В условных операторах не используется оператор присвоения;
  • Запрещено сравнение с NaN. Для проверки, является результат операции числовым, нужно использовать Number.isNaN;
  • Запрещено использовать case без break или return в блоках switch;
  • Не используются вложенные тернарные операторы;

Функции

  • В return не используется оператор присваивания;
  • В стрелочных функциях всегда используются скобки для параметров, даже если параметр один;

Операторы

  • В конструкторе классов-наследников обязательно вызывается super();
  • В конструкторе нет обращения к this до того, как будет вызван super();

Объявление переменных и функций

  • При объявлении переменных используются ключевые слова let и const;
  • Запрещено переопределять с помощью ключевого слова ранее созданные переменные;
  • Запрещено использовать множественное объявление через одно ключевое слово. Для каждой переменной используется отдельный let или const;
let a = 1;
let b = 2;
  • Запрещено переопределение функций, созданных с помощью функционального объявления (Function declaration);
  • Новые функции не создаются с помощью конструктора Function;
  • Вместо коллекции arguments, используется rest-оператор, если это позволяет версия языка;
  • Вместо вызова функции через apply используется spread-оператор, если это позволяет версия языка;
// bad
Math.max.apply(null, [1, 100, 15, 1000]);

// good
Math.max(...[1, 100, 15, 1000]);
  • Не вызываются служебные конструкторы, создающие объекты из глобальной области видимости Math(), JSON(), Reflect();
  • Конструкторы вызываются со скобками, даже если у них нет параметров;
  • Символы (Symbol) создаются вызовом функции Symbol без ключевого слова new;

Приведение типов

  • Не используется лишнее приведение к boolean. Например, нет большого смысла переводить в boolean условия в конструкциях if, while, for, в первом операнде тернарного оператора;
  • Оператор typeof используется корректно - используются только правильные значения, возвращаемые оператором, не производится сравнения со строковыми литералами, которые содержат некорректные значения typeof;
  • В parseInt обязательно передается второй параметр - основание системы счисления, даже в случае с десятичной системой счисления;
  • В блоки условия операторов if, while, for и тернарного оператора не передается константное значение, которое подразумевает, что условие выполняется (или не выполняется) всегда;
// bad
if (true) {}

// good
if (a > 1) {}

Хорошие практики

  • Не используется конструкция with;
  • Не используются alert;
  • Не используется выполнение кода через eval;
  • Встроенные в язык объекты и прототипы не расширяются в рантайме;
  • Не переопределяются глобальные значения (undefined, null, Object, window и прочие);
  • В функциях, которые не являются методами никакого объекта или класса не используется this;

Чистый код

  • Не используются лишние (множественные) точки с запятой;
  • В коде не используется оставленных выводов в консоль;
  • В коде нет забытых инструкций debugger;
  • В проекте нет недоступного кода, который никогда не выполнится;
// bad
if (false) {
    do_something();
}

// good
if (need_something()) {
    do_something();
}
  • В коде нет объявленных, но неиспользуемых переменных;
  • В коде нет выражений, значения которых не записываются в переменные, параметры функций или свойства объектов и не передаются как параметры функций;
// bad
check === true && do_something();

// good
if (check) {
    do_something();
}