Является ли запись объекта в фигурных скобках допустимой в любом выражении?

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

Поскольку функции состоят из нескольких выражений, допустим следующий код:

function valid(){
    /\W/;
    "ahll";
    var alpha;
    alpha;
    alpha={"first": 90, "second": 80};
    alpha;
    0, {"first": 90, "second": 80};
    [1,2,3];
    alpha;
    2+3;
    new RegExp("/\W/");
    return true;
}

Преднамеренно следующий код также должен быть допустимым, но получает синтаксическую ошибку "пропущено; перед оператором" для второй строки:

function invalid(){
    {"first": 90, "second": 80};
    return true;
}

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

Синтаксическая ошибка, упомянутая выше, вызвана реализацией или спецификацией javascript?

Есть ли более точное название для такого бессмысленного выражения?

5 ответов

Решение

Синтаксическая ошибка, упомянутая выше, вызвана реализацией или спецификацией javascript?

По спецификации.

Есть ли более точное название для такого бессмысленного выражения?

Вы ищете термин Expression Statement, Как вы говорите, литералы объектов являются выражениями (даже первичными выражениями), как и большинство других вещей. Они могут появляться во многих контекстах, таких как аргументы функций, операнды оператора или в квадратных скобках.

Однако тело функции - код - не состоит из выражений, оно состоит из операторов. Это означает такие вещи, как операторы if, операторы цикла или простые блоки. Или "операторы выражений", которые являются не чем иным, как выражением, которое нужно оценить (и с побочными эффектами, они в большинстве своем не являются "бессмысленными")

Тем не менее, спецификация обязывает:

ExpressionStatement: [lookahead ∉ {{, function}] Expression ;

ПРИМЕЧАНИЕ. ExpressionStatement не может начинаться с открывающей фигурной скобки, поскольку это может сделать его неоднозначным с блоком. Кроме того, ExpressionStatement не может начинаться с ключевого слова function, потому что это может сделать его неоднозначным с FunctionDeclaration.

То, что вы просматриваете как объект, в последнем примере фактически является блоком:

Из MDN:

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

Итак, в основном, когда вы запускаете фигурные скобки, он понимает, что это блок, и выдает ошибку:

Uncaught SyntaxError: Unexpected token : 

Потому что не любит эти двоеточия (: внутри блока, где ожидаются операторы (var a = 2, так далее.). Предполагается, что все, что следует за фигурной скобкой, должно быть набором утверждений, и поэтому удивляется, увидев двоеточие, и в замешательстве выдает ошибку. Обратите внимание, что "first": 90 не является действительным утверждением.

Тогда почему 0, {"first": 90, "second": 80}; проходить?

Потому что увидев первое выражение (0), а затем оператор запятой, он ожидает увидеть другое значение аналогичного типа (то есть другое выражение). И таким образом это относится ко второму объекту {"first": 90, "second": 80} как объект (который также является выражением) вместо блока.

Чтобы еще больше упростить, попробуйте {"first": 90, "second": 80}, 0, Обратите внимание, что он дает SyntaxError точно такой же, как и предыдущий. Потому что, как только он видит {, он обрабатывает следующее как блок и снова жалуется на двоеточие (:).

Как мне избежать этого?

Делая это частью другого выражения, например:

( {1:2} ) // a block doesn't come inside parentheses
var a = {1 : 2}; // a block can't be the RHS
myFunc( { 1 : 5 } ) // a block can't be a function argument

Надеюсь, поможет!

Парсер имеет приоритет лечить { как начало блока, а не начало объекта.

Итак, что мы делаем, чтобы явно сказать читателю сначала добавить перед умножением, в случае:

3 * 4 + 2

Возможно это:

3 * (4 + 2)

Аналогично для

{"first": 90, "second": 80};

мы могли бы сделать это

({"first": 90, "second": 80}); 

или выразить это другими способами, когда парсер понимает ваше истинное намерение.

В ECMA-262 определено много различных типов выражений. "Выражение", упомянутое во вводном Вопросе, лучше всего соответствует выражению PrimaryExpression, которое описывается так: (каждая строка с отступом является возможным представлением)

PrimaryExpresion:
    this //as the 'this'-keyword
    Identifier //variable or function name ('alpha' in the question)
    Literal //string, number, mathematical expressions
    ArrayLiteral //[1,2,3]
    ObjectLiteral // {"first" : 80}
   ( Expression ) //An expression encapsulated in bracket

Кодовый блок фигурных скобок:

Block :
    { StatementList_opt } - A list of statements

Наиболее актуальное утверждение в этом случае:

ExpressionStatement :
    [lookahead ∉ {{, function}] Expression ;

Это позволяет только выражение без открывающейся фигурной скобки или ключевого слова function в начале. (FunctionDeclarations отделены от операторов и выражений, за исключением лямбда-функций, которые являются FunctionExpression)

Определение Expression напрямую не указывает выражение PrimaryExpression, но в длинной цепочке определений выражение PrimaryExpression может рассматриваться как выражение:

Expression:
    AssignmentExpression
    Expression, AssingmentExpression

Я проверил всю цепочку определений, чтобы увидеть, является ли PrimaryExpression выражением. Вот цепочка определений:

Expression:
    AssignmentExpression:
        ConditionalExpression:
            LogicalORExpression:
                LogicalANDExpression:
                    BitwiseORExpression:
                        BitwiseXORExpression:
                            BitwiseANDExpression:
                                EuqalityExpression:
                                    RelationalExpression:
                                        ShiftExpressions:
                                            AdditiveExpression:
                                                MultiplicativeExpression:
                                                    UnaryExpression:
                                                        PostfixExpression:
                                                            LeftHandSideExpression:
                                                                NewExpression:
                                                                    MemberExpression:
                                                                        PrimaryExpression:

Ответить на вопрос

Нотация объекта в фигурных скобках, указанная как ObjectLiteral в ECMA-262, по определению действительна в каждом выражении, за исключением случая выражения, производного от оператора, поскольку ExpressionStatement явно запрещает вхождение открывающей фигурной скобки в качестве первого символа выражения разрешить конфликт с помощью блока фигурных скобок (определяется как Блок). FunctionBody, Block, Program (глобальная область) и все конструкции цикла (IterationStatements) используют операторы и, следовательно, имеют ограничения, содержащие только блоки, а не ObjectLiterals в разделе кода.

в заключение

Спецификация ограничивает фигурные скобки для представления либо блока кода, либо обозначения объекта. Вьющиеся скобки обрабатываются как блок кода везде, где разрешено использование ключевого слова var, и наоборот.

Это было рассмотрено в предыдущем вопросе здесь

Фигурные скобки используются для введения блока операторов или в качестве начала литерала объекта. Чтобы справиться с этой неоднозначностью, фигурные скобки по умолчанию интерпретируются как контейнеры блоков операторов, таким образом, синтаксическая ошибка в вашем примере.

Когда фигурные скобки используются в RHS оператора, неоднозначность исчезает; это объектный литерал.

Другие вопросы по тегам