2011-09-22 66 views
3

,然後試圖立即訪問他們的屬性:立即訪問鑑於定義對象的這四個實例對象的屬性

{foo: 'bar'}.foo 
// syntax error: unexpected_token 

我預計這將返回「富」的價值,但它會導致語法錯誤。

我能想出的唯一解釋是對象定義尚未執行,因此尚未成爲對象。看來,對象定義因此被忽略和語法錯誤來自試圖只執行:

.foo 
// results in the same syntax error: unexpected_token 

同理:

{foo: 'bar'}['foo'] 
// returns the new Array ['foo'] 

這似乎是證據,文字的對象被忽略,尾隨代碼被執行。

然而,這些做工精細:

({foo: 'bar'}).foo 
// 'bar' 

({foo: 'bar'})['foo'] 
// 'bar' 

括號是用來運行的代碼行,並自認爲括號運算符的結果是實例化對象,你可以訪問屬性。

那麼,爲什麼被忽略的對象定義並不立即執行?

+2

這只是好奇?或者實際上有一個合法的理由來使用:'{foo:'bar'}。foo'? – jfriend00

+2

對語言如何解釋這條線感到好奇。 – wlmeurer

回答

5

它的「背景」的問題,你的前兩個例子不是對象文字!

它們是語句塊,例如:

{ foo: 'bar' } 

上面的代碼被評價爲一個塊,包含labelled statementfoo)指向一個表達式語句(字符串文字'bar')。

當您將它包裝在圓括號中時,代碼將在表達式上下文中進行評估,因此語法與Object Literal語法匹配。

其實還有其他的方法來迫使表達式求值,你會看到,當直接應用於對象文本如財產accesor符號的作品:

({foo:'bar'}.foo); // 'bar' 
0, {foo:'bar'}.foo; // 'bar' 
0||{foo:'bar'}.foo; // 'bar' 
1&&{foo:'bar'}.foo; // 'bar' 
// etc... 

現在,在你的第二個例子:

{foo: 'bar'}['foo'] 

這裏發生的是這兩個語句的評估,首先是塊,然後是包含Array文本的表達式語句。

語法不明確性與函數表達式與函數聲明發生的相似。

參見:

7

它不會被忽略,它只是在這裏不被識別爲對象。

{ ... }在語句開始處被解析爲代碼的Block[spec]

{foo: 'bar'}.foo的情況下,內碼foo: "bar"被解析爲LabelledStatement[spec]

因此{foo: 'bar'}解析正確(即使它不符合您的期望),但屬性訪問語法實際上導致語法錯誤,因爲訪問塊上的屬性無效。


正如您所注意到的解決方案是封閉對象括號:

({foo: 'bar'}).foo 

(啓動語句導致解析器搜索的表達式的括號內。正如您所期望的那樣,當作爲表達式解析爲Object Initializer[spec]時,您可能會收到以下錯誤消息:{foo: 'bar'}


對於{foo: 'bar'}['foo'],它實際上將被解析爲兩個單獨的語句:塊({foo: 'bar'}和數組初始化(['foo']):

{foo: 'bar'}; 
['foo']; 
+0

如果不允許,爲什麼JavaScript不會在{foo:'bar'} ['foo']的情況下返回語法錯誤? – wlmeurer

+2

是的,因爲錯誤狀態 - 這是一個語法錯誤。正確的語法是使用括號。 – gilly3

+0

@elmeurer還要注意「在開始語句」(或在「語句」上下文中)的措詞。雖然不是很漂亮,但這是有效的:'f = {a:「b」}。a' - '{...}'出現在那裏的「表達式」上下文中。 – 2011-09-22 17:04:54