Подписывайтесь на мой твиттер, там всегда что-нибудь интересное!

13 интересных моментов по стилизации JavaScript кода от Google

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

Перевод статьи 13 Noteworthy Points from Google’s JavaScript Style Guide

Там нет строгих правил для написания валидного JavaScript, а есть только советы для написания последовательного и привлекательного кода для всех ваших проектов. Особенно это интересно для JavaScript, который сам по себе гибкий и довольно многообразный язык, позволяющий использовать широкий выбор стилизации кода.

У Google и Airbnb есть два самых популярных стилевых руководства по этой теме. Я определенно советую вам ознакомится с обоими, если вы проводите много времени с JavaScript.

Далее в статье будут тринадцать самых интересных замечаний и релевантных правил из Google JS Style Guide.

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

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

Используйте пробелы, а не табы (табуляцию)

Кроме символа разграничителя строки, ASCII символ горизонтального пробела (0х20) — единственный символ пробела/разграничителя, который появляется где-либо в исходном файле. Это подразумевает то, что Tab символы не используются для отступов.

// плохо
function foo() {
∙∙∙∙let name;
}

// плохо
function bar() {
let name;
}

// хорошо
function baz() {
∙∙let name;
}

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

Каждое объявление должно заканчиваться на точку с запятой.

Запрещается полагаться на автоматическую вставку этих символов.

Хоть я и не могу представить, почему кто-то против этой идеи, но использование точек с запятыми в JS становится новыми дебатами масштаба ‘spaces versus tabs’.

Google твердо обозначил свою позицию в защиту использования точки с запятой.

// плохо
let luke = {}
let leia = {}
[luke, leia].forEach(jedi => jedi.father = 'vader')

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

Пока что не используйте модули ES6

Не применяйте модули из ES6, пока что (т.е. слова export и import), так как их семантика пока не не финализирована. Обратите внимание, что это правило будет пересмотрено, после того, как семантика станет полным стандартом.

// Не делайте пока что такие вещи:
// — — — 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. Не нужно даже продолжать использовать горизонтальные выравнивания в местах, где это уже использовалось.

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

// плохо
{
    tiny:   42,  
    longer: 435, 
  };
  // хорошо
  {
    tiny: 42, 
    longer: 435,
  };

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

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

Я до сих пор вижу людей, которые используют слово var в примерах кода. Не могу сказать, есть ли для этого веские причины или это просто дело долгоумерающей привычки.

// плохо
var example = 42;
// хорошо
let example = 42;

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

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

Буду честен, я просто думал, что стрелочные функции это отлично, потому что они короче и вообще лучше выглядят. Но оказывается, что у них довольно важное предназначение в плане упрощения написания кода.

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

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

Используйте шаблонные строки вместо их объединения

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

// плохо
function sayHi(name) {
  return 'How are you, ' + name + '?';
}

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

// плохо
function sayHi(name) {
  return `How are you, ${ name }?`;
}

// хорошо
function sayHi(name) {
  return `How are you, ${name}?`;
}

Не используйте line continuations для длинных строк

Не применяйте line continuations как в обычных строках, так и в шаблонных строках. Пусть даже ES5 позволяет делать это, такой подход может привести с неловким ошибкам, если какой-нибудь пробел будет после слеша и это менее очевидно для читателей.

Интересен тот момент, что это правило по которому мнения Google и Airbnb расходятся. Вот пример Airbnb.

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

// Плохо (Извините, это не показывается как надо на мобильных)
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.';
// Хорошо
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. Их все можно использовать, хотя for-of циклы должны быть предпочтительнее, если возможно.

Это странно, если вы спросите меня, но я думаю это надо упомянуть, так как довольно интересно, что Google объявил предпочтительный тип цикла loop.

Я был всегда впечатлен тем, что for…in циклы были лучше для объектов, в то время как for…of были лучше для массивов. В общем правильный инструмент для подходящей ситуации.

Пока спецификация Google не противоречит этой идее, до сих пор интересно узнать, почему они сделали предпочтение в сторону этого цикла.

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

Не используйте eval или Function(…string) конструктор, кроме кодлоадеров. Этот функционал потенциально опасен и просто не работает в CSP среде.

На страничке eval() в MDN, даже есть секция под названием “Не используйте eval!”

// плохо
let obj = { a: 20, b: 30 };
let propName = getPropName();  // returns "a" or "b"
eval( 'var result = obj.' + propName );

// хорошо
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

Константы должны именоваться ЗАГЛАВНЫМИ_БУКВАМИ разделенные нижними подчеркиваниями

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

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

// Плохо
const number = 5;
// Хорошо
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;

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

Обычные строчные литералы заключаются в одинарные кавычки, а не в двойные.

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

// плохо
let directive = "No identification of self or mission."
// плохо
let saying = 
'Say it ain\u0027t so.';
// хорошо
let directive = 'No identification of self or mission.';
// хорошо
let saying = `Say it ain't so`;

И напоследок

Как я и сказал вначале, это не строгие правила. Google это просто один из технологических гигантов и это просто рекомендации.

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

Вы можете следовать этим правилам, если хотите. Но всегда будут недовольные и вы спокойно можете пренебречь некоторыми или вообще всеми из этих правил.

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