繁体   English   中英

为什么“new Date()。toString()”在给定Javascript运算符优先级的情况下工作?

[英]Why does “new Date().toString()” work given Javascript operator precedence?

MDN声明 Javscript中有两个操作符具有最高优先级:

  • 左关联成员运算符: foo.bar
  • 右关联new运算符: new Foo()

我通常明确地将两者分开:( (new Date()).toString()
但我经常看到它们都结合在一起: new Date().toString()

根据这个答案 ,第二种方式起作用的原因在于,当两个运算符具有相同的优先级时,它是第二个运算符的关联性。 在这种情况下,成员运算符是左关联的,这意味着首先计算new Date()

但是,如果是这种情况,那么为什么new Date.toString()会失败呢? 毕竟, new Date 只是 new Date() 语法糖 上述论点说它应该有用,但显然不行。

我错过了什么?

语法

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←new NewExpression←new PrimaryExpression:

NewExpression :
    MemberExpression
    new NewExpression

我是那个写了“ 与不同关联性和相同优先级的邻近运算符消除表达式 ”的问题和答案的人,当我写这篇文章时,我脑子里没有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解析器实现的完全不同的正式系统。 我正在讨论的正式系统将运算符和操作数都视为一等值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM