Чем обработка Python для переноса строк отличается от автоматической точки с запятой в JavaScript?

41

Javascript имеет функцию под названием «Автоматическая вставка точек с запятой», в которой, в основном, если синтаксический анализатор обнаруживает недопустимый токен, а последним токеном до этого был разрыв строки, то анализатор вставит точку с запятой в том месте, где находится разрыв строки. Это позволяет вам в основном написать весь свой код JavaScript без точек с запятой, но вы должны знать о некоторых крайних случаях, в основном, если у вас есть ключевое слово return, а затем значение, которое вы хотите вернуть в новой строке.

function test(){
    // This will return 'undefined', because return is a valid statement
    // and  "john" is a valid statement on its own.
    return 
          "john"
}

Из-за этих ошибок есть десятки статей с такими заголовками, как «Автоматическая вставка точки с запятой - это зло», «Всегда используйте точки с запятой в Javascript» и т. Д.

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

def test():
    # This will return 'undefined', because return is a valid statement
    # and  "john" is a valid statement on its own.
    return 
    "john"

Работает точно так же, но никто не боится поведения Питонов.

Я думаю, что случаев, когда javascript ведет себя плохо, достаточно мало, чтобы вы могли легко их избежать. Возврат + значение на новой строке? Люди действительно так много делают?

Есть мнения? Вы используете точку с запятой в javascript и почему?

Эйнар Эгильссон
источник
3
Это не работает точно так же. Вставка точки с запятой не идет везде, где новая строка обязательно находится в JavaScript. Смотрите второй пример на этой странице Википедии . Точка с запятой не вставляется в том месте, где находится символ новой строки в этом примере.
Рейд
1
Моя точка зрения заключалась не в том, что использование точек с запятой и их отсутствие работали одинаково, а дело в том, что крайние случаи в javascript и python были одинаковыми. Конечно, есть несколько крайних случаев, когда вы должны знать, что происходит. Лучшая статья, которую я прочитал на эту тему: inimino.org/~inimino/blog/javascript_semicolons
Эйнар
4
Я ставлю точки с запятой в JavaScript по той же причине, по которой я использую точки в предложениях. Конечно, переводчик может понять ваши заявления без них, но это просто плохая форма.
Джей Ди Айзекс
3
Вы можете подумать о написании правильного Python в ваших примерах. Индикатор комментария #, а не `// '.
Аарон Дюфур
2
«явное всегда лучше, чем неявное»

Ответы:

62

Причина в том, что в Python переводы строки являются однозначным способом разделения строк кода; это сделано специально, и способ, которым это работает, был тщательно продуман. В результате код на python отлично читается и однозначен без каких-либо специальных маркеров конца оператора (кроме новой строки).

Javascript, с другой стороны, был разработан с учетом C-подобного синтаксиса, где операторы всегда заканчиваются точкой с запятой. Чтобы сделать язык более терпимым к ошибкам, он пытается угадать, куда нужно добавить лишние точки с запятой, чтобы сделать код правильным. Поскольку это было как бы встроено в C-подобный синтаксис, оно не всегда работает должным образом (иногда интерпретатор сценариев угадывает) и может привести к довольно нелогичному коду. \

Или, рассуждая в терминах «явный лучше, чем неявный»: в Python новая строка уже полностью явная, а в Javascript она неоднозначная, поэтому вы добавляете точку с запятой, чтобы сделать ее явной.

tdammers
источник
3
О, и вы можете поместить код в комментарии, используя обратные кавычки.
tdammers
1
Хороший пример случая, когда автоматическая вставка
точек с запятой приводит к
5
В Python правила довольно просты: операторы заканчиваются переносами строк, если только не существует незамкнутой многострочной строки ("" ", '' '), незамеченного dict ({}), незамкнутого списка ([]) или обратной косой черты сразу до разрыва строки. В javascript правила значительно сложнее
Аарон Дюфур
5
Покрытие 99% ошибок - это хороший способ оставить позади действительно трудные для поиска ошибки. Можно оставить их в Python, потому что есть простые правила, которые покрывают 100% проблем.
Аарон Дюфур
1
@ Аарон: Вы забыли "открытый набор скобок (())". (Не совсем «незакрытый кортеж», потому что скобки используются не только для кортежей.)
JAB
28

Я думаю, что есть довольно принципиальное отличие от того, как это работает в Python. Цитата из поста Эйнара Эгильссона связана с: «точка с запятой не подразумевается в конце строки, если первый токен следующей строки может быть проанализирован как часть того же оператора».

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

// Define a function and name it area.
area = function(r) {
    return r * r * 3.14159
}

// Fooled you! We're actually invoking it.
(14)
Хенрик
источник
8
Теперь вот забавный поворот на этом. Замените 14 на что-то вроде, (a + 1) ? do_something() : do_something_else();и внезапно, область установлена ​​на возвращаемое значение do_something()или, do_something_else()и вы сильно растерялись.
Рейд
20

Я часто минимизирую свои JS-файлы в производственном режиме. Значит, удаление комментариев и разрывов строк.

Без использования точек с запятой это сломало бы мой Javascript.

Deradon
источник
8
ОК, это действительно. Но если ваш минимизатор является фактическим парсером, он может вставить их снова при необходимости. Или просто не удаляйте разрывы строк, => вы сохраняете разрывы строк, теряете точки с запятой, они примерно одинаковы, поэтому ничего не теряется.
Эйнар Эгильссон
2
@Einar Egilsson Closure Compiler действительно делает это.
Серьезный
1
При прочих равных символе новой строки то же число байтов, что и точка с запятой. Ваш минимизатор может убрать все новые строки, но затем требуется точка с запятой. Это ровный обмен.
Логан Бэйли
3
@Logan: Конечно, это предполагает один байт новых строк ;-)
Кэмерон
1
Конечно, если бы мы использовали Python вместо Javascript, нам пришлось бы кодировать WAY меньше, чтобы делать то же самое, поэтому тот факт, что точки с запятой используют на несколько байтов меньше отступа, является спорным вопросом.
BlueRaja - Дэнни Пфлюгофт
5

Это не работает, как вы описываете.

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

Это не правильно. Пример:

return
  1 + 2;

1является вполне допустимым токеном, но синтаксический анализатор будет вставлять точку с запятой сразу после return.

Как видите, даже вы не можете точно сказать, где будет точка с запятой.

Проблема с автоматической вставкой имеет две стороны:

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

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

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

Сванте
источник
1
Спецификация скрипта ECMA явно указывает, в каких случаях будет вставлена ​​точка с запятой, поэтому ваша строка «Вы не можете точно сказать, где произойдет точка с запятой» неверна. Проблема в том, что в некоторых случаях это не интуитивно понятно, что усложняет обучение тех, кто не понимает, как это работает.
zzzzBov
1
@zzzzBov: Да, есть точная спецификация, но кто-нибудь действительно имеет в виду все случаи при кодировании? Вы уверены? Программисты ленивы, и это справедливо; они не хотят запоминать сложное правило, когда было бы намного проще. Поэтому они пытаются обойти это, вспомнив.
Сванте
Я согласен, что вставка точек с запятой в значительной степени не нужна. Я просто говорю, что есть разница между словами «вы не представляете, куда идут точки с запятой» и «спецификация для вставки
точек с запятой
1
@Svante: Но пример возврата показывает нам, что мы все равно должны знать эти правила. Там вы использовали точку с запятой, но это не помогло вам сделать то, что вы хотели. Итак, учитывая, что в языке есть эта особенность, у нас есть возможность (1) писать точки с запятой везде и знать правила, чтобы мы понимали, что произойдет (2) не писать точки с запятой везде и понимать правила, чтобы мы понимали, что произойдет. Учитывая этот выбор, я бы предпочел пропустить точки с запятой
Эйнар Эгильссон
4

Я бы назвал одну простую причину:

Javascript выглядит "своего рода ява" или "своего рода C-иш". Конечно, это динамический язык, поэтому он выглядит по-другому ... но смирись - есть фигурные скобки. Языки с фигурными скобками обычно имеют точки с запятой. Естественные рефлексы включаются и заставляют ваш палец идти к точке с запятой, прежде чем вы нажмете Enter.

Python, напротив, даже на первый взгляд выглядит совершенно иначе. Следовательно, мало или совсем нет аналогии со «стандартными скучными языками», интуитивно формируется, и когда кто-то входит в «режим питона», отсутствие точек с запятой становится естественным.

Кос
источник
2

Существует ряд веских причин не использовать вставку точек с запятой в JavaScript.

Прежде всего, это потому, что вставка точек с запятой, как определено в стандарте ECMAScript, в некоторых случаях не интуитивна. @Svante указывает на случай, returnкогда использование новой строки вызовет проблемы.

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

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

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

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

zzzzBov
источник
Ах, извините, но относительно вашего третьего пункта, я делать упоминание , что в моем предпоследнем последнее предложение. :)
Сванте
Да, проблема с инструментарием действительна (хотя хорошие минификаторы должны справиться с этим, например, компилятор Closure). Но, на мой взгляд, нам все равно нужно знать эти правила, чтобы избежать таких вещей, как пример «возврата». И как только я узнаю правила, я также могу использовать эту функцию, тем более что она делает код (IMO) более читабельным.
Эйнар Эгильссон
1

Не использовать точку с запятой - это рецепт сбоя при минимизации файлов JavaScript. Вот почему я боюсь этого.

Восточный монах
источник
1

В Javascript вы можете написать программу, которая была бы синтаксически правильной при отсутствии автоматической вставки точек с запятой, и ASI преобразует эту программу в другую синтаксически правильную программу (например, преобразовывая код, который возвращает значение, в код, который ничего не возвращает). Там нет аналогичного случая в Python. В Python любая новая строка, которая может завершить оператор , завершит оператор, если он не экранирован обратной косой чертой. Технически, я предполагаю, что правила Javascript одинаково детерминированы, но я не знаю, можете ли вы обобщить правила Javascript для завершения операторов в одном предложении.

Райан К. Томпсон
источник
1

В большинстве случаев ASI JavaScript обрабатывает все как положено. Один из примеров ASI, возможно, не ведет себя так, как вы ожидаете, это:

var i = 0

(function() {
   // do something
})()

Это будет интерпретироваться как вызов функции 0с анонимной функцией, а затем выполнение результата. В этом случае вы, вероятно, захотите выполнить назначение, а затем немедленно выполнить анонимную функцию.

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

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

jay_soo
источник
1

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

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

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

Почему JavaScript по-прежнему трактуется по-другому?

Там инерция. И не следует упускать из виду, что люди, которые ценят явно структурированный код, часто предпочитают языки в стиле C. Люди, которые ценят неявно структурированный код, часто переходят на языки не в стиле C (например, CoffeeScript).

Закрытие Ковбой
источник
0

Я использую их в Javascript строго для согласованности. Если большинство строк имеют

В Python они есть для крайних случаев, таких как множественные операторы в одной строке, в javascript они есть, и, поскольку вы найдете их регулярно используемыми, я соответствую норме, в которой они используются.

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

Крис
источник
Да, я исправил пример с Python. Но суть в том, что в Python также есть точки с запятой, вы можете ставить их после каждого оператора (и нужно, если у вас более одного в каждой строке), но люди не используют их.
Эйнар Эгильссон
0

Если вы используете что-то вроде bundle-fu и менеджера ресурсов для своего веб-приложения в rails, то оно будет ужасно сломано, если не встретится точка с запятой в конце токена в javascript. Так что это хорошая практика.

subiet
источник
Ну, большая тройка, YUI Compressor, Closure Compiler и UglifyJS, все вставляют точки с запятой. Я не удивлен, что у рубинового порта JSMin есть проблемы.
Бенджамин Аткин
0

Я не могу вспомнить, какая именно версия IE, но в некоторых случаях IE буквально выдает ошибку, если точка с запятой отсутствует. IIRC это когда у вас есть в глобальном масштабе что-то вроде:

var myFunc = function() {
  ...
}

Если вы не добавите; после закрывающей скобки программа действительно завершится с ошибкой в ​​некоторых версиях IE. Это, наряду с другими причинами (включая рекомендацию Крокфорда всегда использовать их явно), заставило меня всегда использовать их явно в каждом случае.

apinstein
источник