[英]Why does “new Date().toString()” work given Javascript operator precedence?
MDN声明 Javscript中有两个操作符具有最高优先级:
foo.bar
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.