簡體   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