2010-06-21 16 views
6

क्या आप समझा सकते हैं कि जावास्क्रिप्ट अभिव्यक्ति कैसे:जावास्क्रिप्ट अभिव्यक्ति [1 [{}]] पार्स वास्तव में कैसे करता है?

[1 [{}]] 

पार/मूल्यांकन करता है? फ़ायरफ़ॉक्स, क्रोम, कॉन्करर, और गैंडो में, ऐसा लगता है कि एक तत्व, undefined के साथ एक सरणी बनाना है। हालांकि, मुझे समझ में नहीं आता क्यों।

फ़ायरफ़ॉक्स में:

[1 [{}]].toSource() 

[(void 0)] 

अन्य जावास्क्रिप्ट मानों के साथ 1 को प्रतिस्थापित करना एक ही परिणाम उत्पन्न करता प्रतीत होता है।

अद्यतन: मुझे लगता है कि अब मैं समझता हूं। कोडेका, एड्रियन, और सीएमएस ने चीजों को स्पष्ट किया। मानक तक, मैंने ईसीएमएस्क्रिप्ट 5 के माध्यम से चलने की कोशिश की। Xzx85

  1. 1 [{}] एक संपत्ति एक्सेसर है, इसलिए यह §11.2.1 में शामिल है।
  2. baseReference1 का मूल्यांकन करने का परिणाम है, फिर भी 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) पर, हम वापस आते हैं (संख्या ऑब्जेक्ट-कोर्सीबल है)।
  8. propertyNameString = ToString(propertyNameValue)
  9. ToString (§9.8) पर, ToString(ToPrimitive({}, hint String))
  10. ToPrimitive (§9.1) पर लौटें, ऑब्जेक्ट के [[DefaultValue]] का परिणाम परिणाम PreferredType (स्ट्रिंग) गुजर रहा है।
  11. [[DefaultValue]] (§8.12.8) पर, [[Get]] का तर्क toString के साथ होने दें।
  12. यह "[object " + [[Class]] + "]" को वापस करने के लिए §15.2.4.2 पर परिभाषित किया गया है, जहां [[Class]] डिफ़ॉल्ट ऑब्जेक्ट प्रोटोटाइप के लिए "ऑब्जेक्ट" है।
  13. चूंकि एक कॉल करने योग्य toString है, इसलिए हम इसे this{} होने के साथ तर्क कहते हैं।
  14. Reference प्रकार का मान लौटाएं, जिसका आधार मान BaseValue (1) है और जिसका संदर्भित नाम propertyNameString ("[object Object]") है।

फिर हम ऐरे प्रारंभकर्ता (§11.1.4) पर जाते हैं, और परिणाम के साथ एक एकल तत्व सरणी बनाते हैं।

+1

मुझे यकीन है कि क्यों यह वैध होगा जावास्क्रिप्ट नहीं कर रहा हूँ ... ताकि आप इंजन * इसे संभाल करने के लिए * कोशिश कर के अप्रत्याशित परिणाम प्राप्त:

अंत में यहाँ कैसे पार्सर अभिव्यक्ति का मूल्यांकन करता है। .. मुझे सामान्य स्थिति सामान्य है। –

+0

@ निक, मुझे यह भी संदेह है कि यह वैध जेएस है, और मैं संभावना को स्वीकार करने के लिए तैयार हूं कि यह केवल अपरिभाषित व्यवहार है। हालांकि, तथ्य यह है कि सभी 4 इंजन (जिनमें अलग-अलग कार्यान्वयन होते हैं) इसे समान रूप से दिलचस्प मानते हैं। –

+1

@ मैथ्यू - एड्रियन का जवाब उन 4 ब्राउज़रों में व्यवहार का एक बहुत अच्छा स्पष्टीकरण है, मुझे अभी भी नहीं लगता कि '[ऑब्जेक्ट]' एक वैध एक्सेसर है हालांकि ... तो यह अभी भी प्रत्येक इंजन पर कैसे होगा इस मामले को संभालेगा। हालांकि यह एक बढ़िया मामला है, और मुझे 3.1 spec में कुछ भी नहीं मिला है जो कहता है कि इसे बिल्कुल कैसे संभाला जाना चाहिए। –

उत्तर

7

अगर हम इसे थोड़ा तोड़ने, आप देखेंगे:

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

[baz]; 

मेरा मानना ​​है कि यह मान्य JavaScript है, लेकिन मैं एक विशेषज्ञ नहीं हूँ ...

+0

मुझे लगता है कि आपके पास यह है। मुझे शायद यह नहीं देखा क्योंकि जावास्क्रिप्ट ऑब्जेक्ट के रूप में किसी संख्या का उपयोग करना असामान्य है, और खाली वस्तु असामान्य कुंजी है। क्या आपके पास '[(शून्य 0)]' भाग पर कोई विचार है? –

+2

@ मैथ्यू: मेरा अनुमान है कि चूंकि '1 [{}] 'अपरिभाषित है,' (शून्य 0) 'केवल" अपरिभाषित "का प्रतिनिधित्व करने के लिए दुभाषिया का" कैननिकल "रूप है। –

8

यह इसलिए है क्योंकि आप वस्तु 1 की संपत्ति {} और फिर एक सरणी में रखने के लिए कोशिश कर रहे हैं। 1 में संपत्ति {} नहीं है, इसलिए 1[{}]undefined है।

यदि आप 1 को किसी सरणी के साथ प्रतिस्थापित करते हैं, तो आप देखेंगे कि यह कैसे काम कर रहा है। 1[5] और {}0 के साथ, यह [[5][0]] है।

इसके अलावा, ध्यान रखें कि obj['property']obj.property जैसा ही है।

15

OP and Nick comments पढ़ना, मुझे लगता है कि मैं इसे स्पष्ट करने के लिए Adrian's answer को थोड़ा और विस्तार कर सकता हूं।

यह पूरी तरह से जावास्क्रिप्ट है।

जावास्क्रिप्ट स्ट्रिंग के रूप में ऑब्जेक्ट संपत्ति नामों को संभालता है, ऑब्जेक्ट्स में अन्य प्रकार या अन्य ऑब्जेक्ट्स कुंजी के रूप में नहीं हो सकते हैं, वे केवल तार हैं।

ब्रैकेट अंकन property accessor (MemberExpression [ Expression ]) परोक्ष एक स्ट्रिंग में कोष्ठक के बीच अभिव्यक्ति बदल देता है, तो:

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

ऊपर के उदाहरण में आप देख सकते हैं कि मैं {} संपत्ति को कोई मान निर्दिष्ट, और {}.toString() (या {}+'') स्ट्रिंग "[object Object] (Object.prototype.toString के माध्यम से) उत्पन्न करता है।

अभिव्यक्ति 1 [{}] परोक्ष धर्मान्तरित 1 Number किसी ऑब्जेक्ट को आदिम (इस संपत्ति एक्सेसर द्वारा किया जाता है) और यह एक संपत्ति "[object Object]" संपत्ति देखने Number.prototype और Object.prototype वस्तुओं पर किया जाता है नाम है, उदाहरण के लिए lookups:

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` 
संबंधित मुद्दे