Автоматическая вставка точек с запятой и возврат
Как вы, возможно, знаете, ECMAscript пытается быть умным и автоматически вставляет точки с запятой, если вы не написали их явно. Простой пример
function foo() {
var bar = 5
return bar
}
все равно будет работать как положено. Но есть некоторые предостережения, если вы полагаетесь на это. Если мы переписать эту функцию так
function foo() {
var bar = 5
return
{
bar: bar
}
}
..это функция теперь будет возвращать undefined
потому что переводчик вставит эту точку с запятой сразу после return
оператор (это причина, почему вы всегда должны ставить фигурные скобки на одной строке с оператором).
Однако, зная все это, я задаюсь вопросом, насколько безопасно return
утверждение, как следующее, для всех браузеров и версий
function foo() {
var a = true,
b = true,
c = false;
return a
&& b
&& c;
}
Я просто написал похожее return statement
в производственной среде. Просто потому, что я знал о "проблемах" с ECMAscript, которые не так умны насчет вставки точек с запятой, мне интересно, если этот код работает на 100%. В моих первых тестах на FF/Chrome/IE (последние версии) это было вполне нормально, но так ли это на самом деле?
Автоматическая вставка точки с запятой "пробуждение", если есть что-то еще, кроме return
утверждение в этой строке? Кто-нибудь может предоставить подробности об уровне реализации об этом?
3 ответа
Интерпретатор / компилятор javascript настолько умен, что вставляет автоматические точки с запятой только в том случае, если впоследствии существует допустимый Javascript.
Ваш код работает, потому что && b
в существующем виде это недопустимое выражение - поэтому точка с запятой не вставляется после return a
в результате чего:
return a && b && c;
Тем не мение:
return (undefined);//implicitely inserted
{
....
}
совершенно правильно, и именно поэтому точка с запятой вставляется.
Для полноты изложения ссылка на спецификацию: автоматическая вставка точки с запятой. Примеры стоит прочитать.
Не зависит от браузера / внедрения, но Section 7.9 Automatic Semicolon Insertion
Спецификации языка ECMAScript стоит прочитать.
7.9 Автоматическая вставка точек с запятой
Некоторые операторы ECMAScript (пустой оператор, оператор переменной, оператор выражения, оператор do-while, оператор continue, оператор break, оператор return и оператор throw) должны заканчиваться точкой с запятой. Такие точки с запятой всегда могут быть явно указаны в исходном тексте. Однако для удобства такие точки с запятой могут быть исключены из исходного текста в определенных ситуациях. Эти ситуации описываются тем, что в этих ситуациях точки с запятой автоматически вставляются в поток токенов исходного кода.
7.9.1 Правила автоматической вставки точек с запятой Есть три основных правила вставки точек с запятой:
Когда при синтаксическом анализе программы слева направо обнаруживается токен (называемый токеном-нарушителем), который не допускается никаким производством грамматики, тогда точка с запятой автоматически вставляется перед токеном-нарушителем, если один или несколько из следующих условия верны:
- Токен-нарушитель отделен от предыдущего токена хотя бы одним LineTerminator.
- Токен-нарушитель -}.
Когда, когда программа анализируется слева направо, встречается конец входного потока токенов, и анализатор не может проанализировать входной поток токенов как одну завершенную программу ECMAScript, тогда точка с запятой автоматически вставляется в конце входной поток.
Когда, когда программа анализируется слева направо, встречается токен, который допускается некоторым производством грамматики, но производство является ограниченным производством, и токен будет первым токеном для терминала или нетерминала, следующего сразу за аннотацией.?[здесь нет LineTerminator]? внутри ограниченного производства (и поэтому такой токен называется ограниченным токеном), и ограниченный токен отделяется от предыдущего токена хотя бы одним LineTerminator, после чего точка с запятой автоматически вставляется перед ограниченным токеном. Однако в предыдущих правилах есть дополнительное переопределяющее условие: точка с запятой никогда не вставляется автоматически, если точка с запятой будет затем проанализирована как пустая инструкция, или если эта точка с запятой станет одной из двух точек с запятой в заголовке инструкции for (см. 12.6.3). ПРИМЕЧАНИЕ. Ниже перечислены единственные ограниченные произведения в грамматике: PostfixExpression: LeftHandSideExpression [здесь нет LineTerminator] ++ LeftHandSideExpression [здесь нет LineTerminator] - ContinueStatement: continue [здесь нет LineTerminator] Identifier; BreakStatement: break [здесь нет LineTerminator] Идентификатор; ReturnStatement: return [здесь нет LineTerminator] Expression; ThrowStatement: throw [no LineTerminator here] Expression; Практический эффект этих ограниченных производств заключается в следующем: когда встречается токен ++ или -, когда синтаксический анализатор рассматривает его как постфиксный оператор, и между предыдущим токеном и токеном ++ или - встречается как минимум один LineTerminator, затем точка с запятой автоматически вставляется перед токеном ++ или -. Когда встречается токен продолжения, разрыва, возврата или броска и встречается LineTerminator перед следующим токеном, точка с запятой автоматически вставляется после токена продолжения, разрыва, возврата или броска. В результате получаются практические советы для программистов на ECMAScript: оператор postfix ++ или - должен находиться в той же строке, что и его операнд. Выражение в выражении return или throw должно начинаться с той же строки, что и токен return или throw. Идентификатор в операторе break или continue должен находиться в той же строке, что и токен break или continue.
7.9.2 Примеры автоматической вставки точек с запятой
Источник
{ 1 2 } 3
не является допустимым предложением в грамматике ECMAScript, даже с правилами автоматической вставки точек с запятой. В отличие от источника
{ 1
2 } 3
также не является допустимым предложением ECMAScript, но преобразуется автоматической вставкой точки с запятой в следующее:
{ 1
;2 ;} 3;
который является действительным предложением ECMAScript. Источник
for (a; b
)
не является допустимым предложением ECMAScript и не изменяется автоматической вставкой точки с запятой, потому что точка с запятой необходима для заголовка оператора for. Автоматическая вставка точки с запятой никогда не вставляет одну из двух точек с запятой в заголовок оператора for. Источник
return
a + b
преобразуется автоматической вставкой точки с запятой в следующее:
return;
a + b;
ПРИМЕЧАНИЕ. Выражение a + b не обрабатывается как значение, возвращаемое оператором return, потому что LineTerminator отделяет его от возврата токена. Источник
a = b
++c
преобразуется автоматической вставкой точки с запятой в следующее:
a = b;
++c;
ПРИМЕЧАНИЕ. Маркер ++ не рассматривается как постфиксный оператор, применяемый к переменной b, поскольку между b и ++ возникает LineTerminator. Источник
if (a > b)
else c = d
не является допустимым предложением ECMAScript и не изменяется автоматической вставкой точки с запятой перед токеном else, даже если в этот момент не применяется обработка грамматики, поскольку автоматически вставленная точка с запятой будет затем проанализирована как пустой оператор. Источник
a = b + c
(d + e).print()
не преобразуется автоматической вставкой точки с запятой, поскольку выражение в скобках, начинающееся со второй строки, можно интерпретировать как список аргументов для вызова функции:
a = b + c(d + e).print()
В тех случаях, когда оператор присваивания должен начинаться с левой круглой скобки, для программиста рекомендуется указывать явную точку с запятой в конце предыдущего оператора, а не полагаться на автоматическую вставку точек с запятой.
Ваше заявление о возврате будет работать правильно во всех браузерах, как указывает Кристоф. Я предпочитаю сделать это еще более явным, если не для компьютеров, но для людей, по крайней мере, разместив операторы и по-другому:
return a &&
b &&
c;
В этом случае никому не нужно тратить секунду, размышляя, не вызовут ли автоматические точки с запятой хаос. Я предпочитаю это только для JavaScript, ваш оригинальный код легче читать.