Каковы правила автоматической вставки точки с запятой в JavaScript (ASI)?



ну, сначала я должен, вероятно, спросить, зависит ли это от браузера.



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



однако общий пример, приведенный для ошибок, вызванных вставкой точки с запятой:



return
_a+b;


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



С другой стороны, разрыв цепочек вызовов работает так, как ожидалось:



$('#myButton')
.click(function(){alert("Hello!")});


есть ли у кого-нибудь более подробное описание правил?

506   4  

4 ответов:

прежде всего, вы должны знать, на какие операторы влияет автоматическая вставка точки с запятой (также известная как ASI для краткости):

  • пустые заявления
  • var сообщении
  • выражение заявлением
  • do-while сообщении
  • continue сообщении
  • break сообщении
  • return сообщении
  • throw сообщении

бетон правила АСИ, описаны в спецификации §11.9.1 правила автоматической вставки точки с запятой

описаны три случая:

  1. когда токен (LineTerminator или }) встречается, что не допускается грамматикой, точка с запятой вставляется перед ним, если:

    • маркер отделен от предыдущего маркера по крайней мере одним LineTerminator.
    • маркер }

    например:

    { 1
    2 } 3
    

    превращается в

    { 1
    ;2 ;} 3;
    

    The NumericLiteral1 соответствует первому условию, следующий маркер является Терминатором строки.
    Элемент 2 соответствует второму условию, следующий токен }.

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

    например:

    a = b
    ++c
    

    превращается в:

    a = b;
    ++c;
    
  3. этот случай происходит, когда токен разрешен некоторым производством грамматики, но производство является ограниченного производства точка с запятой автоматически вставляется перед ограниченным маркером.

    ограничен постановки:

    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 правила автоматической вставки точки с запятой

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

  1. когда, как программа разбирается слева направо, токен (называется обидеть маркер) встречается то, что не допускается никаким производством грамматики, тогда точка с запятой автоматически вставляется перед маркер-нарушитель, если выполняется одно или несколько из следующих условий:
    • оскорбительный токен отделен от предыдущего токена по крайней мере одним LineTerminator.
    • оскорбительный токен }.
  2. когда при разборе программы слева направо обнаруживается конец входного потока токенов и синтаксический анализатор не может разобрать входной поток токенов как один полный ECMAScript Program, затем a точка с запятой автоматически вставляется в конец входного потока.
  3. когда программа анализируется слева направо, встречается токен, который разрешен некоторым производством грамматики, но производство является ограниченного производства и токен будет первым токеном для терминала или нетерминального сразу после аннотации"[нет 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

    Ничего не найдено.