Если оставить их, это выглядит красиво, но это может сломать вещи

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

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

Вскоре я узнал об автоматической вставке точки с запятой (ASI) в JavaScript. По сути, JavaScript будет автоматически ставить точки с запятой, если вы их опускаете. Так что в конце концов, они не являются обязательными.

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

Чтобы избежать выхода из строя Интернета, JavaScript должен быть обратно совместимым. Мы можем добавлять новые функции (ES6, ES7, ES8 и т. Д.), Но мы не можем убирать функции, потому что они уже используются и на которые полагаются. Умышленно или случайно существуют миллионы строк JavaScript, которым для правильной работы необходим ASI. Итак, мы все застряли в этом, но некоторые из нас решают справиться с этим по-разному.

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

Другой лагерь не ставит точки с запятой, полагаясь на ASI, чтобы поставить их автоматически. Их код немного больше похож на Python или Ruby.

Сообщество JavaScript все еще разделено по этому поводу. Например, React по-прежнему включает точку с запятой в своей документации, а Vue - нет.

Vue был моей следующей остановкой в ​​фреймворках JavaScript после jQuery и React, и я решил использовать стиль кодирования без точки с запятой, представленный в документации. Мне он понравился (он делает ваш код намного чище!), И я начал применять этот стиль к другим проектам JavaScript за пределами Vue - например, Node.js.

К сожалению, у меня начались проблемы…

Как автоматическая вставка точки с запятой ломает все: конкретный пример

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

Puppeteer (Headless Chrome Node.js API) казался хорошим способом сделать это, поэтому я попробовал его. В документации есть этот фрагмент кода, с которого вы можете начать:

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});
  await browser.close();
})();

По сути, идея этого кода состоит в том, чтобы импортировать Puppeteer, а затем реализовать anasync IIFE (выражение немедленного вызова функции). Это позволяет вам использовать ключевое слово await для ожидания завершения асинхронных действий (например, запуска браузера) перед переходом к следующему шагу (например, загрузка веб-страницы).

Проверяю, все работает. Кукловод переходит на веб-страницу и, как и ожидалось, делает снимок экрана. Потрясающие.

Но остальной код, который я написал для этого проекта, был написан без точки с запятой. Итак, для единообразия я убрал точки с запятой:

const puppeteer = require('puppeteer')
(async () => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  await page.goto('https://example.com')
  await page.screenshot({path: 'example.png'})
await browser.close()
})()

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

/Users/chris/Documents/code/sandbox/nodejs/puppeteer-test/index.js:3
(async () => {
^
TypeError: require(...) is not a function

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

Node.js не знает, что он должен останавливаться после const puppeteer = require('puppeteer'), потому что в нем нет точки с запятой. Вместо этого он видит открывающую скобку внизу и интерпретирует это как вызов функции. Он видит код примерно так:

const puppeteer = require('puppeteer')(async () => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  await page.goto('https://example.com')
  await page.screenshot({path: 'example.png'})
await browser.close()
})()

Без точки с запятой этот код неоднозначен.

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

Подобные ситуации возникают нечасто, но они случаются иногда, и разработчики JavaScript должны быть к ним готовы.

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

  • Возможно, вы не всегда заранее знаете, где ставить точку с запятой. Фактически, когда что-то ломается, вы можете вообще не знать, что имеете дело с проблемой ASI. Включение точки с запятой по умолчанию может сэкономить много времени, затрачиваемого на отладку.
  • Кажется неправильным иметь точки с запятой в одних местах, а в других нет - мое ОКР не может справиться с такими несоответствиями.

Другое решение - соблюдать разные правила в зависимости от вашей текущей среды. Так сказать, плыть по течению.

Например, вы можете включить точку с запятой при написании ванильного JavaScript, jQuery и Node.js и оставить точку с запятой при написании React и Vue. Несоответствие все еще беспокоит меня, но я предпочитаю это решение упомянутому выше.

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

Резюме

Хорошо это или плохо, но изначально JavaScript был разработан для включения автоматической вставки точки с запятой (ASI), и мы застряли на этом.

Прошло почти 25 лет с момента изобретения языка, а сообщество до сих пор не пришло к консенсусу в отношении лучших практик использования точки с запятой. Некоторым разработчикам нравится включать их, некоторым нравится не учитывать их.

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

В конце концов, точка с запятой не обязательно обязательна, но и не обязательна.