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

А если серьезно: зачем мне ставить точку с запятой после каждой строки моего JavaScript-кода? В чем здесь дело?

Как и в большинстве современных сказок, мое приключение началось с поиска в Google, за которым быстро последовали агрессивные незнакомцы из Интернета.

Я нашел проницательные отзывы, такие как:

«Просто используй их».

or:

ПОСТАВЬТЕ [ЦЕНЗУРОВАНО] ТОЧКИ С ЗАПЯТОЙ!!!

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

В любом случае, вот сделка:

Когда мы сами не применяем точки с запятой, автоматическая вставка точки с запятой (ASI) делает это за нас.

Фактически, в ECMAScript есть три подробных правила для ASI. Суть которой примерно изложена на этом архивном ресурсе Mozilla, а именно:

Если токены формы программы JavaScript с первого по n-й грамматически правильны, а токены с первого по n+1 — нет, и между n-м и n+1-м токенами есть разрыв строки, то синтаксический анализатор пытается проанализировать форму. программа снова после вставки виртуальной точки с запятой между n-й и n+1-й лексемами.

Проще говоря:

const a = 1
const b = a

Становится чем-то вроде:

const a = 1;
const b = a;

В чем смысл?

Точки с запятой служат разделителями операторов для скомпилированного кода JavaScript.

И зачем нам нужно разделять операторы в нашем JavaScript?

Ну вот у нас проблемы:

const a = 1
const b = a
[1, 2, 3].forEach((e) => console.log(e))

Большинство ожидает, что этот код выведет на консоль 1, 2 и 3 соответственно; однако вместо этого мы получаем следующее:

TypeError: Cannot read property 'forEach' of undefined

Странный.

Итак, теперь с точкой с запятой:

const a = 1;
const b = a;
[1, 2, 3].forEach((e) => console.log(e));
1
2
3
=> undefined

Что дает?

Хорошо, если наша предыдущая ошибка была:

TypeError: Cannot read property 'forEach' of undefined

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

Что же тогда на самом деле делает наш АСИ? Вернее, чего не делает наш АСИ?

Если наша установка точки с запятой меняет наш результат, то очевидно, что ASI не ставит ее между этими двумя строками самостоятельно:

const b = a
[1, 2, 3].forEach((e) => console.log(e))

Итак, если мы представим, что наш код полностью скомпилирован, эти две строки, по-видимому, будут выглядеть примерно так:

constb=a[1, 2, 3].forEach((e)=>console.log(e));

Подождите, давайте посмотрим на нашу проблемную область немного подробнее:

... a[1, 2, 3] ...

Казалось бы, без точки с запятой, разделяющей эти операторы, скомпилированный код обрабатывает нашу переменную a как массив с некой формой нотации скобок, предшествующей ей. После этого forEach() вызывается для неопределенного массива.

Интересный. Итак, на что еще мы должны обратить внимание?

Спецификации ECMAScript предлагают несколько других примеров, и вот еще несколько распространенных подводных камней:

return
a + b

Становится:

return;
a + b;

Функция возвращает undefined, потому что ASI отделяет возврат в следующей строке точкой с запятой, фактически отсекая его.

Другой:

a = b
++c

Становится:

a = b;
++c;

Это означает, что если бы оператор «++» увеличивал на два значение b, а не значение c, ASI ошиблась бы.

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

Итак, добро пожаловать в культ; просто используйте их.