2016-01-21 4 views
25

इस कोड:foo.x = foo = {n: 2} में foo.x का अपरिभाषित क्यों है?

var foo = {n: 1}; 
var bar = foo; 
foo.x = foo = {n: 2}; 

आप कृपया व्याख्या कर सकते हैं क्या मतलब है:

foo.x = foo = {n: 2}; 

मुझे लगता है कि {n:2}foo को सौंपा गया है। undefined को foo.x क्यों सौंपा गया है? foo = {n: 2}; वापसी undefined है?

+3

डाउनवोट क्यों? यह एक दिलचस्प सवाल है। – Ben

+0

@ जुहाना क्या आप अपने संपादन को ठीक करना चाहते हैं? – djechlin

+0

@djechlin इसके साथ क्या गलत है? – JJJ

उत्तर

7

क्योंकि संपत्ति का उपयोग बाईं ओर से foo.x पर किया जाता है, दाएं हाथ से पहले मूल्यांकन किया जाता है।

के लिए इसे और अधिक स्पष्ट है कि आपके कोड वास्तव में करता है मूल्यांकन किया जा रहा बनाने के लिए, अस्थायी भाव के लिए नया नाम देकर दो:

var foo0 = {n: 1}; 
var foo1 = {n: 2}; 
foo0.x = foo1; 
foo0 = foo1; 
console.log(foo0.x); 

इसलिए foo0.xfoo1.xundefined है।

अपने मूल कोड में, आप देख सकते हैं कि bar.x{n: 2} है, इस स्पष्टीकरण की पुष्टि।

+0

अब मुझे लगता है कि यह सही है लेकिन मुझे आश्चर्य नहीं है कि यह भ्रमित लोगों है। – djechlin

1

क्योंकि आपने एक ही संपत्ति, { n: 2 } के साथ किसी ऑब्जेक्ट को foo को फिर से असाइन किया है।

जावास्क्रिप्ट में, अभिव्यक्तियों का मूल्यांकन दाएं से बाएं से किया जाता है। तो जब आप foo.x तक पहुंचने का प्रयास करते हैं, तो आप x का मूल्य Foo, { n: 2 } के नए असाइन किए गए मान से प्राप्त करने का प्रयास कर रहे हैं, जो undefined है।

+0

फिर "foo.x =" ... क्या करता है? – djechlin

+0

यह @djechlin foo को सौंप दिया जाता है, लेकिन फिर foo के साथ बाहर एक एक्स मूल्य –

4

जावास्क्रिप्ट कल्पना के अनुसार, बाएं हाथ की ओर हमेशा पहले मूल्यांकन किया जाता है:

12.14.4 रनटाइम शब्दार्थ: मूल्यांकन

AssignmentExpression [में, यील्ड]: LeftHandSideExpression [? यील्ड] = असाइनमेंट एक्स्प्रेशन [? में,? यील्ड]

तो LeftHandSideExpression न तो एक ObjectLiteral है और न ही एक ArrayLiteral, तो
1. lref LeftHandSideExpression के मूल्यांकन का परिणाम हो सकता है।

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-assignment-operators-runtime-semantics-evaluation

यह स्पष्ट रूप से अगर आप foo वस्तु के लिए एक और संदर्भ जोड़ने के देखा जा सकता है:

var ref = {n:1}; 
var foo = ref; 
var bar = foo; 
foo.x = foo = {n: 2}; 

ref.x मौजूद है क्योंकि foo.xfoo की असंशोधित मूल्य को दर्शाता है।

23

According to the spec, असाइनमेंट अभिव्यक्ति के बाएं हाथ की तरफ पहले मूल्यांकन किया जाता है, भले ही ऑपरेटर को दाएं से बाएं प्राथमिकता हो। इस प्रकार अभिव्यक्ति foo.x = foo = {n: 2} जो foo.x = (foo = {n: 2}) रूप में ही है इस तरह मूल्यांकन किया जाता है:

  1. बाएं हाथ की अभिव्यक्ति foo.x मूल्यांकन के लिए एक संदर्भ है, जो जहां दाएँ हाथ अभिव्यक्ति के मूल्य को सौंपा जाएगा मिलता है।

  2. दाएं हाथ की अभिव्यक्ति का मूल्यांकन करें, ताकि वह मूल्य प्राप्त किया जा सके। दाएँ हाथ की ओर एक और काम अभिव्यक्ति है, तो यह उसी तरह का मूल्यांकन किया जाता है:

    1. मूल्यांकन foo निर्धारित करने के लिए जहां के लिए आवंटित करने के लिए।
    2. अभिव्यक्ति का मूल्य निर्धारित करने के लिए {n:2} अभिव्यक्ति का मूल्यांकन करें, जो ऑब्जेक्ट बनाता है।
    3. foo को {n:2} असाइन करें, और {n:2} वापस करें।

  3. , मूल्य कि दाईं ओर स्थित अभिव्यक्ति के लिए ({n:2}) का मूल्यांकन किया निरुपित संदर्भ के लिए है कि foo.x चरण 1 में का संकल्प (से पहलेfoo एक नया मान सौंपा गया था)। इससे पहले bar = foo असाइनमेंट की वजह से bar.x जैसा भी है।

जब ऐसा होता है, मूल वस्तु, कि bar एक संदर्भ के लिए अब भी है, एक x संपत्ति का संदर्भ देता है बनाया दूसरी वस्तु होगा। foo उस दूसरी वस्तु का संदर्भ भी है, इसलिए foo === bar.x

+0

ऐसा लगता है कि हम एक विजेता है एक वस्तु को ओवरराइड है। – Ben

+0

कैसे करता है 'foo.x = (foo = {n: 2})' भी मतलब नहीं है कि विपरीत होना चाहिए, मैं तो बस क्रोम में भी परीक्षण किया है कि और यह एक ही परिणाम –

+1

@ johnny5 यह नहीं होगा है भावना यदि 'foo' पहले से ही एक वस्तु नहीं था, लेकिन यह पहले बयान से, है। – Paulpro

संबंधित मुद्दे