2010-06-21 33 views
6

你能解釋JavaScript表達式如何:JavaScript表達式[1 [{}]]究竟如何解析?

[1 [{}]] 

解析/評估板?在Firefox,Chrome,Konqueror和rhino中,它似乎創建了一個包含單個元素的數組undefined。但是,我不明白爲什麼。

在Firefox:

[1 [{}]].toSource() 

產生

[(void 0)] 

與其他JavaScript值替換1似乎產生相同的結果。

更新:我想我現在明白了。 codeka,Adrian和CMS澄清了事情。至於標準,我試圖通過的ECMAScript 5

  1. 1 [{}]走路是一個屬性訪問器,所以它的覆蓋§11.2.1。
  2. baseReference是評估結果1,所以仍然1
  3. baseValue = GetValue(baseReference) == 1
  4. GetValue(§8.7.1),Type(1)不是Reference(解析的名稱綁定),所以返回1
  5. propertyNameReference是評估{},所以空對象的結果。
  6. propertyNameValue = GetValue(propertyNameReference) == {}
  7. CheckObjectCoercible(baseValue)(§9.10),我們返回(Number是對象強制的)。
  8. propertyNameString = ToString(propertyNameValue)
  9. ToString(§9.8),返回ToString(ToPrimitive({}, hint String))
  10. ToPrimitive(第9.1節),對象的[[DefaultValue]]的返回結果,通過PreferredType(串)。
  11. [[DefaultValue]](§8.12.8),令toString爲[[Get]]的結果,其參數toString
  12. 這是在§15.2.4.2定義的,返回"[object " + [[Class]] + "]",其中[[Class]]是默認對象原型的「Object」。
  13. 由於有一個可召集的toString,我們稱它爲this{}
  14. 返回類型爲Reference的值,其基值爲BaseValue(1),其參考名稱爲propertyNameString"[object Object]")。

然後,我們轉到數組初始值設定項(第11.1.4節),並用結果構造單個元素數組。

+1

我不知道爲什麼,這將是有效的JavaScript ...所以你得到發動機*試圖*處理它的不可預知的結果。 ..似乎對我來說很正常。 – 2010-06-21 00:24:12

+0

@尼克,我也懷疑它是有效的JS,並且我願意接受它可能只是未定義的行爲。但是,所有4個引擎(它們都有獨立的實現)以相同的方式解析它的事實至少是有趣的。 – 2010-06-21 00:31:44

+1

@Matthew - Adrian的回答是對這4個瀏覽器中行爲的一個很好的解釋,但我仍然不認爲'[object]'是一個有效的訪問器,儘管...所以它仍然取決於每個引擎如何會處理這種情況。儘管這是一個邊緣案例,我無法在3.1規範中找到任何說明它應該如何處理的內容。 – 2010-06-21 00:55:17

回答

7

如果我們把它分解一下,你會看到:

var foo = 1; 
var bar = {}; 
var baz = foo[bar]; 

[baz]; 

我相信它是有效的JavaScript,但我不是專家...

+0

我認爲你有它。我可能沒有看到這個,因爲使用一個數字作爲JavaScript對象並不常見,而空對象是一個不尋常的關鍵。你對'[(void 0)]'部分有任何想法嗎? – 2010-06-21 00:55:40

+2

@Matthew:我的猜測是由於'1 [{}]'是未定義的,'(void 0)'僅僅是解釋器用於表示「未定義」的「規範」形式。 – 2010-06-21 01:15:48

8

這是因爲您試圖獲取對象1的屬性{},然後將其放入數組中。 1沒有財產{},所以1[{}]undefined

如果用數組替換1,您將看到它是如何工作的。用1作爲[5]{}作爲0,它是[[5][0]]

此外,請記住obj['property']obj.property相同。

15

閱讀OP and Nick comments,我想我可以擴大一點點Adrian's answer使其更清晰。

這是完全有效的JavaScript。

JavaScript將對象屬性名稱視爲字符串,對象不能包含其他類型或其他對象,如,它們只是字符串。

的括號記號property accessorMemberExpression [ Expression ])括號內的表達式隱式轉換成一個字符串,所以:

var obj = {}; 
obj[{}] = "foo"; 
alert(obj["[object Object]"]); // foo 

在上面的例子可以看出,我分配一個值到{}屬性,和{}.toString()(或{}+'')產生字符串"[object Object](通過Object.prototype.toString)。

表達1 [{}]隱式轉換的1 Number原語的一個對象(這是由屬性訪問製造),它查找命名"[object Object]"屬性查找是對Number.prototypeObject.prototype對象所做的屬性,例如:

1['toString'] === Number.prototype.toString; // true 

最後,1 [{}]表達式本身被括在括號內([1 [{}]]),這實際上是一個數組文字。

總之這裏是語法分析器如何計算表達式:

[1 [{}]]; 
// ^The accessor expression is evaluated and converted to string 

[1 ["[object Object]"]]; 
//^A property lookup is made on an Number object 
// trying to access a property named "[object Object]" 

[undefined]; 
// ^the property is obviously not found 

    [undefined]; 
//^  ^
// An array literal is created with an element `0` which its value is `undefined`