Каковы правила автоматической вставки точки с запятой (ASI) в JavaScript?
Ну, сначала я должен, вероятно, спросить, зависит ли это от браузера.
Я прочитал, что если найден недопустимый токен, но раздел кода действителен до этого недопустимого токена, точка с запятой вставляется перед токеном, если ему предшествует разрыв строки.
однако общим примером ошибок, вызванных вставкой точки с запятой, является:
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;
на
NumericLiteral
1
соответствует первому условию, следующий токен является Терминатором строки.
The2
соответствует второму условию, следующий токен}
. - маркер отделен от предыдущего маркера по крайней мере одним
-
при обнаружении конца входного потока токенов и невозможности синтаксического анализа входного потока токенов как единого полного Программа, затем точка с запятой автоматически вставляется в конце входного потока.
например:
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, затем точка с запятой автоматически вставляется перед ограниченным маркером.однако в предыдущих правилах есть дополнительное условие переопределения: точка с запятой никогда не вставляется автоматически, если точка с запятой будет затем проанализирована как пустой оператор или если эта точка с запятой станет одной из двух точек с запятой в заголовке на заявление (см. 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 интерпретирует разрывы строк как точки с запятой, когда он не может разобрать вторую строку как продолжение оператора на первой строке. Первое исключение включает в себя return, break и continue заявления
... Если после любого из этих слов появляется разрыв строки ... 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 в предыдущей строке больше не применялось, поскольку этот оператор считался законченным из-за автоматической вставки с запятой.