Каковы правила автоматической вставки точки с запятой в JavaScript (ASI)?
ну, сначала я должен, вероятно, спросить, зависит ли это от браузера.
Я читал, что если найден недопустимый токен, но раздел кода действителен до этого недопустимого токена, точка с запятой вставляется перед токеном, если ему предшествует разрыв строки.
однако общий пример, приведенный для ошибок, вызванных вставкой точки с запятой:
return
_a+b;
..который, похоже, не следует этому правилу, так как _a будет действительным знак.
С другой стороны, разрыв цепочек вызовов работает так, как ожидалось:
$('#myButton')
.click(function(){alert("Hello!")});
есть ли у кого-нибудь более подробное описание правил?
4 ответов:
прежде всего, вы должны знать, на какие операторы влияет автоматическая вставка точки с запятой (также известная как ASI для краткости):
- пустые заявления
varсообщении- выражение заявлением
do-whileсообщенииcontinueсообщенииbreakсообщенииreturnсообщенииthrowсообщениибетон правила АСИ, описаны в спецификации §11.9.1 правила автоматической вставки точки с запятой
описаны три случая:
когда токен (
LineTerminatorили}) встречается, что не допускается грамматикой, точка с запятой вставляется перед ним, если:
- маркер отделен от предыдущего маркера по крайней мере одним
LineTerminator.- маркер
}например:
{ 1 2 } 3превращается в
{ 1 ;2 ;} 3;The
NumericLiteral1соответствует первому условию, следующий маркер является Терминатором строки.
Элемент2соответствует второму условию, следующий токен}.когда обнаружен конец входного потока токенов и синтаксический анализатор не может проанализировать входной поток токенов как один полный Программа, затем точка с запятой автоматически вставляется в конце входного потока.
например:
a = b ++cпревращается в:
a = b; ++c;этот случай происходит, когда токен разрешен некоторым производством грамматики, но производство является ограниченного производства точка с запятой автоматически вставляется перед ограниченным маркером.
ограничен постановки:
UpdateExpression : LeftHandSideExpression [no LineTerminator here] ++ LeftHandSideExpression [no LineTerminator here] -- ContinueStatement : continue ; continue [no LineTerminator here] LabelIdentifier ; BreakStatement : break ; break [no LineTerminator here] LabelIdentifier ; ReturnStatement : return ; return [no LineTerminator here] Expression ; ThrowStatement : throw [no LineTerminator here] Expression ; ArrowFunction : ArrowParameters [no LineTerminator here] => ConciseBody YieldExpression : yield [no LineTerminator here] * AssignmentExpression yield [no LineTerminator here] AssignmentExpressionклассический пример, с помощью тега
ReturnStatement:return "something";превращается в
return; "something";
прямиком из ECMA-262, пятое издание ECMAScript спецификация:
7.9.1 правила автоматической вставки точки с запятой
есть три основных правила вставки точки с запятой:
- когда, как программа разбирается слева направо, токен (называется обидеть маркер) встречается то, что не допускается никаким производством грамматики, тогда точка с запятой автоматически вставляется перед маркер-нарушитель, если выполняется одно или несколько из следующих условий:
- оскорбительный токен отделен от предыдущего токена по крайней мере одним
LineTerminator.- оскорбительный токен }.
- когда при разборе программы слева направо обнаруживается конец входного потока токенов и синтаксический анализатор не может разобрать входной поток токенов как один полный ECMAScript
Program, затем a точка с запятой автоматически вставляется в конец входного потока.- когда программа анализируется слева направо, встречается токен, который разрешен некоторым производством грамматики, но производство является ограниченного производства и токен будет первым токеном для терминала или нетерминального сразу после аннотации"[нет
LineTerminatorздесь]" в рамках ограниченного производства (и, следовательно, такой знак называется ограниченный токен), и ограниченный токен отделяется от предыдущего токена по крайней мере одним LineTerminator, затем точка с запятой автоматически вставляется перед ограниченным маркером.однако в предыдущих правилах есть дополнительное условие переопределения: точка с запятой никогда не вставляется автоматически, если точка с запятой затем будет проанализирована как пустой оператор или если эта точка с запятой станет одной из двух точек с запятой в заголовке a на заявление (см. 12.6.3).
я не мог понять эти 3 правила в спецификациях слишком хорошо-надеюсь, что есть что-то более простое на английском языке-но вот что я собрал из JavaScript: The Definitive Guide, 6th Edition, David Flanagan, O'Reilly, 2011:
цитата:
JavaScript не рассматривает каждый разрыв строки как точку с запятой: он обычно рассматривает разрывы строк как точки с запятой, только если он не может разобрать код без точек с запятой.
еще одна цитата: для кода
var a a = 3 console.log(a)JavaScript не рассматривает второй разрыв строки как точку с запятой, потому что он может продолжать разбор более длинного оператора a = 3;
и:
два исключения из общего правила, что JavaScript интерпретирует разрывы строк как точки с запятой, когда он не может разобрать вторую строку как продолжение оператора на первой строке. Первое исключение включает возврат, разрыв и продолжение заявления
... Если после любого из этих слов появляется разрыв строки ... JavaScript всегда будет интерпретировать эти строки точку с запятой.
... Второе исключение касается операторов ++ и--... Если вы хотите использовать любой из этих операторов в качестве постфиксных операторов, они должны отображаться в той же строке, что и выражение, к которому они применяются. В противном случае разрыв строки будет рассматриваться как точка с запятой, а ++ или -- будут проанализированы как префиксный оператор, применяемый к код, который следует. Рассмотрим этот код, например:
x ++ yон разбирается как
x; ++y;, а неx++; yтак что я думаю, чтобы упростить его, это означает:
в общем, JavaScript будет рассматривать его как продолжение кода, пока это имеет смысл - за исключением 2 случаев: (1) после некоторых ключевых слов, таких как
return,break,continue, и (2) если он видит++или--на новой строке, то он добавит;в конце предыдущей строки.часть о "рассматривать его как продолжение кода, пока это имеет смысл" заставляет его чувствовать себя жадным соответствием регулярного выражения.
С выше сказанным, что означает для
returnпри разрыве строки интерпретатор JavaScript вставит;(снова цитируется: если после любого из этих слов появляется разрыв строки [например
return] ... JavaScript всегда будет интерпретировать это разрыв строки в виде точки с запятой)и по этой причине, классический пример
return { foo: 1 }не будет работать так, как ожидалось, потому что интерпретатор JavaScript будет рассматривать его как:
return; // returning nothing { foo: 1 }должно быть разрыва строки сразу после
return:return { foo: 1 }для его правильной работы. И вы можете вставить
;себя, если вы должны были следовать правилу использования;после любого заявлении:return { foo: 1 };
Что касается вставки точки с запятой и оператора var, будьте осторожны, забывая запятую при использовании var, но охватывая несколько строк. Кто-то нашел это в моем коде вчера:
var srcRecords = src.records srcIds = [];он выполнялся, но эффект состоял в том, что объявление/назначение srcIds было глобальным, потому что локальное объявление с var в предыдущей строке больше не применялось, поскольку этот оператор считался завершенным из-за автоматической вставки точки с запятой.
Comments