Development

Как писать читаемый код на JavaScript: советы от Google

Google выпустил руководство по стилю JavaScript-кода, которое должно стать дорожной картой с лучшими стилистическими подходами для написания чистого и понятного кода.

Прежде чем мы начнём хотелось бы упомянуть, что это не жесткие и неукоснительные правила написания валидного JavaScript-кода, а скорее рекомендации, которых стоит придерживаться для соблюдения последовательного и приемлемого стиля во всех файлах исходного кода.

В этой связи взгляд разработчиков Google особенно интересен в отношении JavaScript, поскольку это очень гибкий язык, допускающий широкое разнообразие вариантов стиля при написания кода.

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

Используйте пробелы, а не табы

Помимо перевода строки, горизонтальный символ пробела (0x20) ASCII это единственный пробельный символ, используемый в файле исходного кода. Это означает, что символы табуляции не используются для отступов.

Далее в руководстве уточняется, что для создания отступов следует использовать два пробела (не четыре). Лично я использую всегда 4 пробела, потому что таким образом структура кода приобретает большую выразительность при её чтении.

// bad
function foo() {
∙∙∙∙let name;
}

// bad
function bar() {
∙let name;
}

// good
function baz() {
∙∙let name;
}

// excellent (мой выбор)
function baz() {
∙∙∙∙let name;
}

Точки с запятыми обязательны

Каждое предложение должно отделяться точкой с запятой. Полагаться на автоматическую вставку точек с запятыми запрещается. Последовательное использование точек с запятыми в JS становится новым спорным моментом наравне с битвами «пробелы vs табы». В этом вопросе Google явно становится на сторону защитников точки с запятой.

// bad
let luke = {}
let leia = {}
[luke, leia].forEach(jedi => jedi.father = 'vader')

// good
let luke = {};
let leia = {};
[luke, leia].forEach((jedi) => {
  jedi.father = 'vader';
});

Используйте модули ES6 с особой осторожностью

Семантика модулей в ES6 (например, ключевые слова export и import) еще не завершена. Поэтому стоит повременить с использованием этих ключевых слов в своих проектах. Скорее всего эта проблема со временем будет решена и мы сможем использовать всю мощь JS в следующих версиях ECMAScript.

// Don't do this kind of thing yet:
//------ lib.js ------
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

//------ main.js ------
import { square, diag } from 'lib';

Горизонтальное выравнивание не поощряется

Эта практика допускается, но в целом не поощряется инженерами Google. Также не требуется поддерживать горизонтальное выравнивание в тех местах, где оно уже использовалось.

Горизонтальное выравнивание это метод добавления различного числа дополнительных пробелов в вашем коде для того чтобы определенные токены появлялись строго под другими токенами на предыдущих строках.

// bad
{
  tiny:   42,  
  longer: 435
};

// good
{
  tiny: 42, 
  longer: 435
};

Больше не используйте var

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

// bad
var example = 42;

// good
let example = 42;

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

Стрелочные функции придают краткость синтаксису и исправляют многие сложности, с ним связанные. Отдавайте предпочтение стрелочным функциям, а не ключевым словам, особенно для вложенных функций.

// bad
[1, 2, 3].map(function (x) {
  const y = x + 1;
  return x * y;
});

// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});

Используйте строки шаблона вместо конкатенации

Используйте строки шаблона (отделенные с помощью ` – одинарной кавычки), а не сложную конкатенацию строк, особенно если задействованы несколько строковых литералов. Строки шаблона могут охватывать несколько строк.

// bad
function sayHi(name) {
  return 'How are you, ' + name + '?';
}

// bad
function sayHi(name) {
  return ['How are you, ', name, '?'].join();
}

// bad
function sayHi(name) {
  return `How are you, ${ name }?`;
}

// good
function sayHi(name) {
  return `How are you, ${name}?`;
}

Не используйте обратный слэш для длинных строк

Не используйте символ продолжения строки (т. е., \ – обратный слэш) для окончания строки внутри строкового литерала, как в обычных, так и в шаблонных строковых литералах.

Несмотря на то, что ES5 это допускает, это может привести к замысловатым ошибкам, если после обратного слэша последует пробел. Кроме того, это менее понятно для читателя.

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

// bad (sorry, this doesn't show up well on mobile)
const longString = 'This is a very long string that \
    far exceeds the 80 column limit. It unfortunately \
    contains long stretches of spaces due to how the \
    continued lines are indented.';

// good
const longString = 'This is a very long string that ' + 
    'far exceeds the 80 column limit. It does not contain ' + 
    'long stretches of spaces since the concatenated ' +
    'strings are cleaner.';

«for… of» предпочтительней, чем цикл for

С ES6 в языке теперь три вида циклов. Все они могут использоваться, хотя следует отдавать предпочтение циклам for… of, если это возможно. Интересен сам факт, что Google отдает предпочтение определенному виду циклов. Мне всегда казалось, что циклы for… in лучше для объектов, а for… of больше подходят для массивов. Хотя спецификация Google не обязательно противоречит этой идее, все равно интересно знать, что они отдают предпочтение именно этому виду циклов.

Не используйте eval()

Не используйте eval или конструктор Function(…string), особенно для загрузчиков кода. Эти свойства являются потенциально опасными и попросту не работают в CSP-окружениях.

Страница MDN, посвященная eval(), даже содержит раздел под названием «Не используйте eval!».

// bad
let obj = { a: 20, b: 30 };
let propName = getPropName();  // returns "a" or "b"
eval( 'var result = obj.' + propName );
// good
let obj = { a: 20, b: 30 };
let propName = getPropName();  // returns "a" or "b"
let result = obj[ propName ];  //  obj[ "a" ] is the same as obj.a

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

Имена констант используют CONSTANT_CASE, то есть все буквы в режиме Caps Lock, слова разделяются символом подчеркивания.

Если вы абсолютно уверены, что значение в коде не должно меняться (это прямой признак константы), вы можете обозначить это, написав ее имя только заглавными буквами. Это делает неизменность константы очевидной, где бы в вашем коде она не использовалась.

В этом правиле есть исключение: константа, ограниченная областью функции. В этом случае ее имя должно писаться в camelCase.

Так как определение константы в стиле CONSTANT_CASE подразумевает её глобальную область видимости, то есть доступ к ней может быть осуществлён из любого места в коде.

Стоит не забывать, что это всё условности и ими многие пренебрегают, а зря!

// bad
const number = 5;

// good
const NUMBER = 5;

Объявляйте переменные по одной

Объявление каждой локальной переменной объявляет только одну переменную: такие объявления, как let a = 1, b = 2; не используются.

// bad
let a = 1, b = 2, c = 3;

// good
let a = 1;
let b = 2;
let c = 3;

Используйте одинарные, а не двойные кавычки

Обычные строковые литералы ограничиваются одинарной кавычкой (‘), а не двойной (“).

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

// bad
let directive = "No identification of self or mission."

// bad
let saying = 'Say it ain\u0027t so.';

// good
let directive = 'No identification of self or mission.';

// good
let saying = `Say it ain't so`;

Заключительное примечание

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