Код должен быть максимально читаемым и понятным.
Это и есть искусство программирования – взять сложную задачу и написать такой код для её решения, который и правильно работает, и легко читается, понятен для людей. Для этого нужен хороший стиль написания кода. В этой главе мы рассмотрим составляющие такого стиля.
Синтаксис
Шпаргалка с правилами синтаксиса (подробнее смотрите ниже по тексту):
Не всё здесь однозначно, так что разберём эти правила подробнее.
Ни одно правило не является жёстко обязательным
Здесь нет железных правил. Это стилевые предпочтения, а не религиозные догмы.
Фигурные скобки
В большинстве JavaScript проектов фигурные скобки пишутся в так называемом «египетском» стиле с открывающей скобкой на той же строке, что и соответствующее ключевое слово – не на новой строке. Перед открывающей скобкой должен быть пробел, как здесь:
if (condition) {
// делай это
// ...и это
// ...и потом это
}
А что если у нас однострочная запись, типа if (condition) doSomething(), должны ли мы использовать фигурные скобки?
Вот различные варианты расстановки скобок с комментариями, посмотрите сами, какой вам кажется самым читаемым:
😠 Такое иногда бывает в коде начинающих. Плохо, фигурные скобки не нужны:
if (n < 0) {alert(‘Степень n не поддерживается’);}
😠 Никогда не разделяйте строки без фигурных скобок, можно ненароком сделать ошибку при добавлении строк:
if (n < 0)
alert(‘Степень n не поддерживается’);
😏 В одну строку без скобок – приемлемо, если эта строка короткая:
if (n < 0) alert(‘Степень n не поддерживается’);
😃 Самый лучший вариант:
if (n < 0) {
alert(‘Степень n не поддерживается’);
}
Для очень короткого кода допустима одна строка. Например: if (cond) return null. Но блок кода (последний вариант) обычно всё равно читается лучше.
Длина строки
Никто не любит читать длинные горизонтальные строки кода. Лучше всего разбивать их, например:
// обратные кавычки ‘ позволяют разделять строку на части
var str= ‘
Рабочая группа TC39 организации Ecma International -
это группа JavaScript-разработчиков, теоретиков и авторов движков JavaScript,
которые вместе с сообществом занимаются поддержкой и развитием языка JavaScript.
Или для if:
if (
id === 123 &&
moonPhase === 'Waning Gibbous' &&
zodiacSign === 'Libra'
) {
varTheSorceryBegin();
}
Максимальную длину строки согласовывают в команде. Обычно это 80 или 120 символов.
Отступы
Существует два типа отступов:
Горизонтальные отступы: два или четыре пробела.
Горизонтальный отступ выполняется с помощью 2 или 4 пробелов, или символа табуляции (клавиша Tab). Какой из них выбрать – это уже на ваше усмотрение. Пробелы больше распространены.
Одно из преимуществ пробелов над табуляцией заключается в том, что пробелы допускают более гибкие конфигурации отступов, чем символ табуляции.
Например, мы можем выровнять аргументы относительно открывающей скобки:
show(parameters,
aligned, // 5 пробелов слева
one,
after,
another
) {
// ...
}
Вертикальные отступы: пустые строки для разбивки кода на «логические блоки».
Даже одну функцию часто можно разделить на логические блоки. В примере ниже разделены инициализация переменных, основной цикл и возвращаемый результат:
function pow(x, n) {
var result = 1;
// <--
for (var i = 0; i < n; i++) {
result *= x;
}
// <--
return result;
}
Вставляйте дополнительный перевод строки туда, где это сделает код более читаемым. Не должно быть более 9 строк кода подряд без вертикального отступа.
Точка с запятой
Точки с запятой должны присутствовать после каждого выражения, даже если их, казалось бы, можно пропустить.
Есть языки, в которых точка с запятой необязательна и редко используется. Однако в JavaScript бывают случаи, когда перенос строки не интерпретируется, как точка с запятой, что может привести к ошибкам. Подробнее об этом – в главе о структуре кода.
Если вы – опытный разработчик на JavaScript, то можно выбрать стиль кода без точек с запятой, например StandardJS. В ином случае, лучше будет использовать точки с запятой, чтобы избежать подводных камней. Большинство разработчиков их ставят.
Уровни вложенности
Уровней вложенности должно быть немного.
Например, в цикле бывает полезно использовать директиву continue, чтобы избежать лишней вложенности.
Например, вместо добавления вложенного условия if, как здесь:
for (var i = 0; i < 10; i++) {
if (cond) {
... // <- ещё один уровень вложенности
}
}
Мы можем написать:
for (var i = 0; i < 10; i++) {
if (!cond) continue;
... // <- нет лишнего уровня вложенности
}
Аналогичная ситуация – с if/else и return.
Например, две нижеследующие конструкции идентичны.
Первая:
function pow(x, n) {
if (n < 0) {
alert("Отрицательные значения 'n' не поддерживаются");
} else {
var result = 1;
for (var i = 0; i < n; i++) {
result *= x;
}
return result;
}
}
Вторая:
function pow(x, n) {
if (n < 0) {
alert("Отрицательные значения 'n' не поддерживаются");
return;
}
var result = 1;
for (var i = 0; i < n; i++) {
result *= x;
}
return result;
}
Второй вариант является более читабельным, потому что «особый случай» n < 0 обрабатывается на ранней стадии. После проверки можно переходить к «основному» потоку кода без необходимости увеличения вложенности.
Размещение функций
Если вы пишете несколько вспомогательных функций, а затем используемый ими код, то существует три способа организации функций.
Объявить функции перед кодом, который их вызовет:
// объявление функций
function createElement() {
...
}
function setHandler(elem) {
...
}
function walkAround() {
...
}
// код, который использует их
var elem = createElement();
setHandler(elem);
walkAround();
Сначала код, затем функции
// код, использующий функции
var elem = createElement();
setHandler(elem);
walkAround();
// --- вспомогательные функции ---
function createElement() {
...
}
function setHandler(elem) {
...
}
function walkAround() {
...
}
Смешанный стиль: функция объявляется там, где она используется впервые.
В большинстве случаев второй вариант является предпочтительным.
Это потому, что при чтении кода мы сначала хотим знать, что он делает. Если сначала идёт код, то это тут же становится понятно. И тогда, может быть, нам вообще не нужно будет читать функции, особенно если их имена хорошо подобраны.
Итого
Все правила синтаксиса, описанные в этой главе (и в ссылках на руководства по стилю), направлены на повышение читаемости вашего кода. О любых можно поспорить.
Когда мы думаем о написании «лучшего» кода, мы должны задать себе вопросы: «Что сделает код более читаемым и лёгким для понимания?» и «Что может помочь избегать ошибок?». Это – основные моменты, о которых следует помнить при выборе и обсуждении стилей кода.
Задачи
Плохой стиль
Какие недостатки вы видите в стиле написания кода этого примера?
function pow(x,n)
{
var result=1;
for(var i=0;i<n;i++) {result*=x;}
return result;
}
var x=prompt("x?",''), n=prompt("n?",'')
if (n<=0)
{
alert(‘Степень ${n} не поддерживается, введите целую степень, большую 0’);
}
else
{
alert(pow(x,n))
}
Решение:
Вы могли заметить следующие недостатки, сверху вниз:
function pow(x,n) // <- отсутствует пробел между аргументами
{ // <- фигурная скобка на отдельной строке
var result=1; // <- нет пробелов вокруг знака =
for(var i=0;i<n;i++) {result*=x;} // <- нет пробелов
// содержимое скобок { ... } лучше вынести на отдельную строку
return result;
}
var x=prompt("x?",''), n=prompt("n?",'') // <-- технически допустимо,
// но лучше написать в 2 строки, также нет пробелов и точки с запятой
if (n<0) // <- нет пробелов, стоит добавить отступ в одну строку сверху
{ // <- фигурная скобка на отдельной строке
// ниже - слишком длинная строка, лучше разбить для улучшения читаемости
alert(‘Степень ${n} не поддерживается, введите целую степень, большую 0’);
}
else // <- можно на одной строке, вместе: "} else {"
{
alert(pow(x,n)) // вложенный вызов функции, нет пробелов и точки с запятой
}
Исправленный вариант:
function pow(x, n) {
var result = 1;
for (var i = 0; i < n; i++) {
result *= x;
}
return result;
}
var x = prompt("x?", "");
var n = prompt("n?", "");
if (n < 0) {
alert(‘Степень ${n} не поддерживается,
введите целую степень, большую 0’);
} else {
alert( pow(x, n) );
}