2013-02-22 55 views
5

निम्नलिखित अंश from ECMA-262 v5.1 (जो मैंने हाल ही में this question में देखा था) पर विचार करें:कैच क्लॉज का अपना लेक्सिकल वातावरण क्यों होता है?

एक शाब्दिक पर्यावरण एक विनिर्देश विशिष्ट चरों और कार्यों ECMAScript कोड का शाब्दिक नेस्टिंग संरचना पर आधारित करने के लिए पहचानकर्ता के सहयोग से परिभाषित किया जाता प्रकार है । एक व्याख्यात्मक पर्यावरण में पर्यावरण रिकॉर्ड और बाहरी लेक्सिकल पर्यावरण के संभावित रूप से शून्य संदर्भ शामिल हैं। आम तौर पर एक लेक्सिकल एनवायरनमेंट ईसीएमएस्क्रिप्ट कोड की कुछ विशिष्ट सिंटैक्टिक संरचना से जुड़ा होता है जैसे फंक्शनडेक्लेरेशन, एक विस्टामेंटमेंट, या ट्रास्टेटमेंट का कैच क्लॉज और हर बार ऐसे कोड का मूल्यांकन किया जाता है, जब एक नया लेक्सिकल एनवायरनमेंट बनाया जाता है।

मैंने सोचा था कि, मतलब catch खंड के शरीर की अपनी चर फहराने हैं कार्यों करते हैं लेकिन जाहिरा तौर पर that's not the case:

var a = 1; 
try { 
    console.log(x); // ReferenceError 
} catch(ex) { 
    console.log(a); // 1, not undefined 
    var a = 3; 
} 

किसी को भी पता है क्यों? इसके अलावा, catch खंड को अपने स्वयं के शब्दावली पर्यावरण की आवश्यकता क्यों है?

+0

रहे हैं "एक बाहरी शाब्दिक पर्यावरण के लिए संभवतः अशक्त संदर्भ।" इसका मतलब यह भी शून्य नहीं हो सकता है, और जब शून्य नहीं होता है, तो यह वैश्विक चर को ठीक लगेगा। –

+0

@ माइक'पोमैक्स 'कमरमैन मैं वास्तव में उम्मीद कर रहा था कि' पकड़ 'में अपने स्थानीय चर हो सकते हैं, जो ग्लोबल्स को छाया दे रहे हैं। लेकिन ऐसा नहीं हो सकता है, क्योंकि इसके लिए बनाए गए लेक्सिकल एनवायरनमेंट एक और प्रकार का है (बर्गी का जवाब देखें, और [10.3] पर spec (http://www.ecma-international.org/ecma-262/5.1/#sec -10.3))। – bfavaretto

उत्तर

5

हाँ, catch खंडों में वास्तव में अपने स्वयं के लेक्सिकल वातावरण हैं। देखें कि happens when it is evaluated: यह एक नया बनाता है (वर्तमान से प्राप्त) और इसे अपवाद-पहचानकर्ता को बांधता है। कैच ब्लॉक को निष्पादित करते समय, वर्तमान Execution Context'sLexicalEnvironment को नए पर स्विच किया जाता है, जबकि VariableEnvironment ("जिसका पर्यावरण रिकॉर्ड VariableStatements और FunctionDeclarations द्वारा निर्मित बाइंडिंग रखता है") अपरिवर्तित रहता है।

console.log(a); // undefined - declared from within the catch, 
       // but in the current VariableEnvironment 
a = 1; 
console.log(typeof ex); // undefined - no binding 
try { 
    console.log(ex); // a ReferenceError in this LexicalEnvironment 
} catch (ex) { // introducing the new LexicalEnvironment 
    console.log(ex); // …and it works here! 
    var a = 3; // variable declaration 
} 

मज़ेदार तथ्य: आप करने की कोशिश की घोषणा एक catch खंड के अंदर एक समारोह (हालांकि वाक्य रचना एक ब्लॉक में अवैध, "समारोह घोषणा बयान" अक्सर स्वीकार किए जाते हैं), इसके दायरे वर्तमान बन जाएगा VariableEnvironment तो यह अपवाद उपयोग करने में सक्षम नहीं होगा:

try {throw "some"} catch(x) { function y(){console.log(x, typeof x);} y(); } 
        // throws a ReferenceError for x ^

(अपडेट: अब यह ES6, जहां में सच है ब्लॉक स्तर समारोह घोषणाओं वैध और ब्लॉक गुंजाइश अधिक करीब)

+0

अब आपने यह कहा है, यह पूरी तरह से समझ में आता है कि अपवाद ऑब्जेक्ट के लिए एक अलग रिकॉर्ड की आवश्यकता है। जब आप कहते हैं कि 'वेरिएबल एंटरटेनमेंट' वही रहता है, तो यह है कि विनिर्देश यह नहीं कहता कि एक नया बनाया जाना चाहिए, या क्या यह स्पष्ट रूप से कहा गया है कि इसे वही रहना चाहिए? – bfavaretto

+0

हाँ, यह स्पष्ट रूप से नहीं बताया गया है, लेकिन चूंकि लेक्सिकल एनवायरनमेंट निष्पादन संदर्भ का एक अलग घटक है, इसलिए मुझे नहीं लगता कि परिवर्तनीय पर्यावरण क्या बदल जाएगा - और कोई नया संदर्भ स्थापित नहीं है, केवल वर्तमान में संशोधित किया गया है (और ब्लॉक निष्पादन के बाद रीसेट करें)। – Bergi

+0

धन्यवाद, यह अभी स्पष्ट है। मैंने सीखा कि वैरिएबल एनवायरनमेंट एक ही निष्पादन संदर्भ में कभी नहीं बदलता है, इसलिए 'पकड़' से होने वाली प्रभाव संभव नहीं है। यह कार्यों में होता है क्योंकि वे ब्रांड नए निष्पादन संदर्भ बनाते हैं। – bfavaretto