[英]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.