Подтвердить что ты не робот

Почему "new Date(). ToString()" работает с приоритетом Javascript-оператора?

MDN утверждает, что в Javscript есть два оператора, которые имеют самый высокий приоритет:

  • Лево-ассоциативный оператор-член: foo.bar
  • Право-ассоциативный новый оператор: new Foo()

Я обычно явно разделяю два: (new Date()).toString()
Но я часто вижу, что оба они объединены: new Date().toString()

В соответствии с этим ответом причина, по которой работает второй способ, заключается в том, что вторая операторная ассоциативность имеет значение, когда оба оператора имеют одинаковый приоритет. В этом случае оператор-член остается ассоциативным, что означает, что new Date() оценивается первым.

Однако, если это так, то почему new Date.toString() терпит неудачу? В конце концов, new Date просто синтаксический сахар для new Date(). В приведенном выше аргументе говорится, что он должен работать, но, очевидно, этого не делает.

Что мне не хватает?

4b9b3361

Ответ 1

Синтаксис

MemberExpression :
    PrimaryExpression
    FunctionExpression
    MemberExpression [ Expression ]
    MemberExpression . IdentifierName
    new MemberExpression Arguments

new foo().bar не может быть проанализирован как new (foo().bar), потому что foo().bar не является MemberExpression. Более того, new foo() не может быть проанализирован как new (foo()) по той же причине. Напротив, new foo.bar анализируется как new (foo.bar), потому что foo.bar является допустимым MemberExpression (интерпретация (new foo).bar невозможна, потому что грамматика является жадным).

То есть, правило приоритета: dot beats new, new beats call (parens).

.  -> new -> ()

Кроме того, глядя прямо на грамматику, демистифицирует синтаксический сахар, который превращает new Foo в new foo(). Это просто NewExpression ← новое NewExpression ← новое PrimaryExpression:

NewExpression :
    MemberExpression
    new NewExpression

Ответ 2

Я тот парень, который написал как вопрос, так и ответ "Разнообразие выражений с соседними операторами различной ассоциативности и того же приоритета", и когда я написал что у меня не было JavaScript в моем сознании.

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

С другой стороны, JavaScript является традиционным языком программирования, а выражения в JavaScript неоднозначны на основе сложных правил синтаксического анализа, которые сильно отличаются от правил синтаксического анализа, используемых Haskell.

В частности, правила синтаксического анализа JavaScript кажутся жадными. Например, возьмите свой первый пример:

new Date().toString()

Здесь вызов функции после Date экранирует Date от оператора-члена. Следовательно, new, будучи жадным, все еще может работать только на Date вместо Date().toString. Следовательно, имеем:

((new Date()).toString)()

Во втором примере мы имеем:

new Date.toString()

Здесь нет функции вызова после Date, чтобы защитить ее от оператора-члена. Следовательно, new, будучи жадным, действует на выражение Date.toString. Следовательно, имеем:

(new (Date.toString))()

@thg435 ответ подтверждает это требование. Дело в том, что я обсуждал формальную систему, которая полностью отличается от той, которая реализована парсерами JavaScript. Формальная система, которую я обсуждал, обрабатывает операторы и операнды как значения первого класса.