Точка с запятой в Javascript

Нужно ли ставить точку с запятой в конце операторов в JavaScript?

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

Почему же JavaScript не требует строгого использования точки с запятой? Потому, что он сам виртуально добавляет их в нужные места. Процесс, который делает это, называется автоматической вставкой точки с запятой (Automatic Semicolon Insertion (ASI)) и описан в стандарте языка.

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

В чем смысл автоматической вставки точки с запятой?

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

Из спецификации:

Некоторые операторы ECMAScript должны заканчиваться точкой с запятой. Такие точки с запятой всегда могут быть явно указаны в исходном тексте.

Но далее говорится:

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

Вот простой пример кода, согласно спецификации, эти операторы переменных должны заканчиваться точкой с запятой:

var a = 1
var b = 2
var c = 3

Эти синтаксические ошибки исправлены при анализе, и код будет считаться следующим:

var a = 1;
var b = 2;
var c = 3;
Правила автоматической вставки точки с запятой в JavaScript

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

  1. Следующая строка начинается с кода, который прерывает текущий (код может появляться на нескольких строках);
  2. Следующая строка начинается с фигурной скобки }, закрывающей текущий блок;
  3. Когда достигнут конец файла исходного кода;
  4. Если встречается return на отдельной строке;
  5. Если встречается break на отдельной строке;
  6. Если встречается continue на отдельной строке;
  7. Если встречается throw на отдельной строке.
Примеры кода, который делает не то, что вы ожидаете

Основываясь на этих правилах, вот несколько примеров:

const hi = 'Привет'
const name = 'Петя'
const hiYou = hi + ', ' + name

['a', 'b', 'c'].forEach((letter) => console.log(letter))

Вы получите сообщение об ошибке: error: Uncaught TypeError: Cannot read property 'forEach' of undefined, потому что на основе 1 правила JavaScript пытается интерпретировать код как:

const hi = 'Привет'
const name = 'Петя'
const hiYou = hi + ', ' + name['a', 'b', 'c'].forEach((letter) => console.log(letter))

Такая строка (1 + 2).toString() выведет "3", но вот такой код:

const a = 1
const b = 2
const c = a + b
(a + b).toString()

вместо этого вызывает исключениеerror: Uncaught TypeError: b is not a function, потому что JavaScript пытается интерпретировать его как:

const a = 1
const b = 2
const c = a + b(a + b).toString()

Очень часто встречается проблема, связанная с ключевым словом return (правило 4):

var a = function() {
  var b = 'ответ'
  return 
  {
    answer: b
  }
}
console.log(a());

Можно было бы ожидать, что возвращаемое значение этой функции будет объектом, содержащим свойство answer, но это не так. Этот код синтаксически неверен, и его лучше рассматривать как синтаксическую ошибку. Грамматическое правило для оператора return выглядит следующим образом:

return [no LineTerminator here] Expression ;

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

return;
{
  answer: b
}

Поэтому вернется значение undefined, а не объект. Вставка точки с запятой не исправт ситуацию, но вот удаление перевода на друную строку заставит наш код работать правильно:

var a = function() {
  var b = 'ответ'
  return {
    answer: b
  }
}
console.log(a());

Можно подумать, что этот код выведет в консоль 0:

1 + 1
-1 + 1 === 0 ? console.log(0) : console.log(2)

но вместо этого он выведет 2, потому что JavaScript согласно правила 1 интерпретирует это как:

1 + 1 -1 + 1 === 0 ? console.log(0) : console.log(2)

Вот еще один пример. В следующем фрагменте кода пропустили запятую после переменной a :

var a 
    b = 2;

console.log(a);
console.log(b);

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

var a; 
    b = 2;

console.log(a);
console.log(b);

Эта проблема немного более тонкая. Включение точки с запятой приведет к объявлению переменной b в глобальной области видимости. Это вызовет ошибку "Uncaught ReferenceError: b is not defined" в строгом режиме.

Ключевым моментом является то, что эта может иметь очень тонкие побочные эффекты, которые трудно выявить в большом коде.


Код:

function add(a,b) {return a+b}

Будет рассматриваться интрепретатором (правило 2) как:

function add(a,b) {return a+b;}
Когда не следует использовать точку с запятой?

Вот несколько случаев, когда точки с запятой не нужны:

if (...) {...} else {...}
for (...) {...}
while (...) {...}

Но требуется согласно стандарта для

do {...} while (...);

После объявления функции точка с запятой также не нужна:

function myfunc (arg) {...}

Но нужна после объявления функционального выражения:

let myfunc = function (arg) {
    ...
};

Если вы напишите:

var i = 0;
do { i++; console.log(i) } while ( i < 5 )

Технически это недопустимая программа, так как конечная точка с запятой отсутствует, но ASI (автоматическая вставка точки с запятой) обработает ее в вид:

var i = 0;
do { i++; console.log(i) } while ( i < 5 );
Итоги

Можно писать и с использованием точек с запятой и без. В разных компаниях свои стили. Так в требованиях по стилю кодированя на Javascript в Google использование автоматической вставки точки с запятой запрещено. Некоторые компании опускают необязательные точки с запятой.

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

const a = 1
const b = 2
const c = a + b
;(a + b).toString()

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

Распространенное заблуждение состоит в том, что "use strict" (строгий режим) JavaScript подавляет функцию ASI. Это не так. Единственный способ избежать этой функции — убедиться, что точка с запятой всегда вставляется в правильном месте. Наиболее эффективный способ обнаружения отсутствующих в JavaScript запятой осуществляется с помощью инструмента статического анализа кода, таких как JSHint или JSLint или можно использовать компилятор Javascript babeljs.io.