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

В настоящее время я немного анализирую язык 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?

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


person schwer    schedule 23.03.2014    source источник
comment
возможный дубликат Почему {} != ( {} ) в JavaScript?   -  person Bergi    schedule 23.03.2014


Ответы (5)


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

По спец.

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

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

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

Однако спецификация требует:

ExpressionStatement: [просмотр ∉ {{, function}] Expression ;

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

person Bergi    schedule 23.03.2014

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

Из МДН:

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

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

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

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

person Gaurang Tandon    schedule 23.03.2014
comment
@slebetman Спасибо :) Я был разочарован после того, как за аналогичные мои прошлые посты проголосовали - 3 из них за последнюю неделю. Еще раз спасибо :) Я действительно благодарен вам. - person Gaurang Tandon; 23.03.2014

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

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

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

person Nacht Blaad    schedule 23.03.2014

Синтаксический анализатор имеет приоритет для обработки { как начала блока, а не начала объекта.

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

3 * 4 + 2

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

3 * (4 + 2)

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

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

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

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

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

person loxxy    schedule 23.03.2014
comment
Я бы с осторожностью относился к привязке фигурных скобок к области видимости, поскольку (а) JS имеет только две области видимости (глобальную, функциональную) и (б) фигурные скобки не создают области видимости, как это принято считать во многих других приложениях. языки, ориентированные на фигурные скобки. - person Dave Newton; 23.03.2014
comment
Согласен, удалил нежелательное отношение. - person loxxy; 23.03.2014

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

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 ;

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

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

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', и наоборот.

person schwer    schedule 23.03.2014