जावास्क्रिप्ट के ये स्निपेट अलग-अलग तरीके से व्यवहार करते हैं, भले ही वे दोनों एक त्रुटि का सामना करते हों?


107

var a = {}
var b = {}

try{
  a.x.y = b.e = 1 // Uncaught TypeError: Cannot set property 'y' of undefined
} catch(err) {
  console.error(err);
}
console.log(b.e) // 1

var a = {}
var b = {}

try {
  a.x.y.z = b.e = 1 // Uncaught TypeError: Cannot read property 'y' of undefined
} catch(err) {
  console.error(err);
}

console.log(b.e) // undefined


3
@ नीनासोल: मुझे समझ नहीं आ रहा है। कोई सिंटैक्स त्रुटि नहीं है; इसलिए मैं यह मानूंगा b.z = 1और b.e = 1पहले निष्पादित करूंगा (सही-सह-समरूपता को देखते हुए =), फिर a.x.y.z = ...निष्पादित और असफल; bएक मामले में असाइनमेंट पास क्यों होता है लेकिन दूसरे में नहीं?
आमदन

3
@NinaScholz हम सहमत हैं कि संपत्ति yमौजूद नहीं है a.x; लेकिन यह दोनों मामलों में सच है। यह दूसरे मामले में दाहिने-हाथ के काम को क्यों रोकता है लेकिन पहले को नहीं? निष्पादन के क्रम में क्या अलग है? (मैंने सिंटैक्स त्रुटि का उल्लेख किया है क्योंकि सिंटैक्स त्रुटि पर समय एक रनटाइम त्रुटि से बहुत अलग है।)
आमदन

@ कोड चलाने के बाद आप त्रुटि प्राप्त करेंगे, और मूल्य देखने के लिए फिर से चर नाम से उपयोग करने की तुलना में
कोड पागल

2
इसने यह वर्णन किया कि कैसे जावास्क्रिप्ट कार्य असाइनमेंट ऑपरेशन ecma-international.org/ecma-262/5.1/#sec-11.13
सोलोमन टैम

2
यह एक सैद्धांतिक दृष्टिकोण से दिलचस्प है, लेकिन यह निश्चित रूप से "यह है कि आप इस तरह से कोड क्यों नहीं लिखते" अनपेक्षित व्यवहार की श्रेणी में आता है।
जॉन मोंटगोमरी

जवाबों:


152

दरअसल, यदि आप त्रुटि संदेश को ठीक से पढ़ते हैं, तो केस 1 और केस 2 अलग-अलग त्रुटियां हैं।

मामला a.x.y:

अपरिभाषित की संपत्ति 'y' निर्धारित नहीं कर सकते

मामला a.x.y.z:

अपरिभाषित की संपत्ति 'y' नहीं पढ़ सकते हैं

मुझे लगता है कि इसे आसान अंग्रेजी में चरण-दर-चरण निष्पादन द्वारा वर्णित करना सबसे अच्छा है।

मामला एक

// 1. Declare variable `a`
// 2. Define variable `a` as {}
var a = {}

// 1. Declare variable `b`
// 2. Define variable `b` as {}
var b = {}

try {

  /**
   *  1. Read `a`, gets {}
   *  2. Read `a.x`, gets undefined
   *  3. Read `b`, gets {}
   *  4. Set `b.z` to 1, returns 1
   *  5. Set `a.x.y` to return value of `b.z = 1`
   *  6. Throws "Cannot **set** property 'y' of undefined"
   */
  a.x.y = b.z = 1
  
} catch(e){
  console.error(e.message)
} finally {
  console.log(b.z)
}

केस 2

// 1. Declare variable `a`
// 2. Define variable `a` as {}
var a = {}

// 1. Declare variable `b`
// 2. Define variable `b` as {}
var b = {}

try {

  /**
   *  1. Read `a`, gets {}
   *  2. Read `a.x`, gets undefined
   *  3. Read `a.x.y`, throws "Cannot **read** property 'y' of undefined".
   */
  a.x.y.z = b.z = 1
  
} catch(e){
  console.error(e.message)
} finally {
  console.log(b.z)
}

टिप्पणियों में, सोलोमन टैम ने असाइनमेंट ऑपरेशन के बारे में ईसीएमए प्रलेखन पाया ।


57

परिचालन का क्रम स्पष्ट होता है जब आप कोमा संचालक के अंदर कॉमा संचालक का शोषण करते हैं यह देखने के लिए कि कौन से हिस्से कब निष्पादित किए जाते हैं:

var a = {}
var b = {}

try{
 // Uncaught TypeError: Cannot set property 'y' of undefined
  a
    [console.log('x'), 'x']
    [console.log('y'), 'y']
    = (console.log('right hand side'), b.e = 1);
} catch(err) {
  console.error(err);
}
console.log(b.e) // 1

var a = {}
var b = {}

try {
  // Uncaught TypeError: Cannot read property 'y' of undefined
  a
    [console.log('x'), 'x']
    [console.log('y'), 'y']
    [console.log('z'), 'z']
    = (console.log('right hand side'), b.e = 1);
} catch(err) {
  console.error(err);
}

console.log(b.e) // undefined

युक्ति को देखते हुए :

उत्पादन AssignmentExpression : LeftHandSideExpression = AssignmentExpressionका मूल्यांकन निम्नानुसार किया जाता है:

  1. बता दें कि Lref, LeftHandSideExpression के मूल्यांकन का परिणाम है।

  2. मान लें कि असाइनमेंट असाइनमेंट के मूल्यांकन का परिणाम है।

  3. रवल होने दो GetValue(rref)

  4. एक सिंटेक्सऑयर अपवाद को फेंक दें यदि ... (अप्रासंगिक)

  5. पुकारते हैं PutValue(lref, rval)

PutValueक्या है TypeError:

  1. हे होने दो ToObject(base)

  2. यदि कॉल करने का परिणाम है [[CanPut]] तर्क P के साथ O आंतरिक विधि गलत है, तो

    ए। यदि थ्रो सत्य है, तो एक टाइपर अपवाद को फेंक दें।

कुछ भी नहीं दिया जा सकता है undefined- की [[CanPut]]आंतरिक विधि undefinedहमेशा वापस आ जाएगीfalse

दूसरे शब्दों में: दुभाषिया बाएं हाथ की तरफ, फिर दाएं हाथ की तरफ पार्स करता है, फिर एक त्रुटि फेंकता है यदि बाईं ओर की संपत्ति को सौंपा नहीं जा सकता है।

जब तुम करोगे

a.x.y = b.e = 1

बाएं हाथ की ओर सफलतापूर्वकPutValue बुलाया गया है जब तक ; तथ्य यह है कि .xसंपत्ति का मूल्यांकन undefinedतब तक नहीं माना जाता है जब तक कि दाएं हाथ की ओर पार्स नहीं किया जाता है। दुभाषिया इसे "अपरिभाषित की" y "संपत्ति के लिए कुछ मूल्य निर्दिष्ट करता है, और undefinedकेवल अंदर फेंकता की संपत्ति के रूप में देखता है PutValue

इसके विपरीत:

a.x.y.z = b.e = 1

दुभाषिया कभी उस बिंदु पर नहीं जाता है जहां वह zसंपत्ति को सौंपने की कोशिश करता है , क्योंकि इसे पहले a.x.yएक मूल्य पर हल करना होगा । यदि a.x.yएक मान (यहां तक ​​कि undefined) के लिए हल किया जाता है , तो यह ठीक होगा - PutValueऊपर की तरह एक त्रुटि अंदर फेंक दी जाएगी । लेकिन एक्सेस करने में a.x.y त्रुटि होती है, क्योंकि प्रॉपर्टी yको एक्सेस नहीं किया जा सकता है undefined


20
नाइस कॉमा ऑपरेटर ट्रिक - कभी इसे इस तरह से इस्तेमाल करने के लिए नहीं सोचा (केवल डिबगिंग के लिए, निश्चित रूप से)!
ecraig12345

2
s / parse / मूल्यांकन /
बर्गी

3

निम्नलिखित कोड पर विचार करें:

var a = {};
a.x.y = console.log("evaluating right hand side"), 1;

कदम के किसी न किसी रूपरेखा निष्पादित करने के लिए कोड के रूप में इस प्रकार की आवश्यकता रेफरी :

  1. बाएं हाथ का मूल्यांकन करें। दो बातों का ध्यान रखें:
    • अभिव्यक्ति का मूल्यांकन करना अभिव्यक्ति के मूल्य प्राप्त करने के समान नहीं है।
    • संपत्ति अभिग्रहण रेफरी का मूल्यांकन उदा उदाहरण के आधार मूल्य (अपरिभाषित) और संदर्भित नाम ( ) से मिलकर a.x.yएक संदर्भ रेफरी करता है ।a.xy
  2. दाहिने हाथ की ओर का मूल्यांकन करें।
  3. चरण 2 में प्राप्त परिणाम का मूल्य प्राप्त करें।
  4. चरण 1 में प्राप्त संदर्भ के मूल्य को चरण 3 में प्राप्त मान पर सेट करें अर्थात yमान के लिए अपरिभाषित की संपत्ति सेट करें । यह एक TypeError अपवाद रेफरी फेंकना माना जाता है ।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.