2013-02-23 46 views
9

मुझे जावास्क्रिप्ट चर के लिए स्कोपिंग के एक विशिष्ट मामले के आसपास अपना सिर नहीं लग रहा है। मुझे मिले अन्य उदाहरणों और प्रश्नों से अलग, मुझे नेस्टेड कार्यों के लिए स्कोपिंग में रूचि है।जावास्क्रिप्ट स्थानीय स्कोपिंग: var बनाम यह

मैंने this JSFiddle पर एक उदाहरण स्थापित किया है।

function MyObject() { 
    var self = this; 

    var a = 1; 
    this.b = 2; 

    var innerMethod = function() { 
     //1 and 2: direct reference 
     logMessage("a = " + a); // a = 1 
     //logMessage("b = " + b); // Error: b is not defined 

     //3 and 4: using this 
     logMessage("this.a = " + this.a); // this.a = undefined 
     logMessage("this.b = " + this.b); // this.b = undefined 

     //5 and 6: using self 
     logMessage("self.a = " + self.a); // self.a = undefined 
     logMessage("self.b = " + self.b); // self.b = 2 
    } 
} 

अब, मैं समझता हूँ कि a के लिए एक संदर्भ सीधे काम करता है: प्रासंगिकता का पीछा कर रहा है। मैं यह भी समझता हूं कि संदेश 3 और 4 (this.a और this.b) विफल हो जाएंगे क्योंकि this आंतरिक फ़ंक्शन को संदर्भित करता है। मैं यह भी समझता हूं कि लाइन 6 काम करता है क्योंकि मैं मूल वस्तु के संदर्भ को सहेजता हूं।

क्या मुझे समझ नहीं आता है:

  • क्यों गए संदेशों 1 और 2 के लिए एक जैसे काम नहीं कर रहे हैं?
  • संदेश 5 और 6 समान रूप से क्यों काम नहीं कर रहे हैं?
+5

पर खेल सकते हैं क्यों वे एक जैसे काम करेगा? ऐसा लगता है कि आप जावा या किसी अन्य भाषा के साथ समानता कर रहे हैं जहां 'यह' नामस्थान अंतर्निहित है, जो जेएस के लिए मामला नहीं है। –

+0

@ FabrícioMatté मैं यह बेहोश हो सकता है (पन इरादा)। मैं समझने में असफल रहा कि क्या स्कोपिंग को चर/सदस्यों को स्वचालित रूप से आंतरिक सदस्यों के सामने उजागर करना चाहिए। ऐसा लगता है कि यह मामला नहीं है, क्योंकि यह संगत नहीं है। – Alpha

+3

@Alpha आप चर तुलना कर रहे हैं ('वर एक = 5;') कि चर लेकिन वस्तुओं ('के गुणों this.b = 10 नहीं कर रहे हैं चीजों के साथ;' संपत्ति 'वस्तु की b' कि' this' संदर्भित करता है सेट '10' तक)। ये चीजें समान नहीं हैं और इसलिए समान व्यवहार नहीं करती हैं। – Niko

उत्तर

4

a वैरिएबल सिर्फ एक चर है। यह innerMethod (जो केवल एक नेस्टेड फ़ंक्शन है) के दायरे में दिखाई देता है, a के रूप में, जिसे यह घोषित किया गया था (यानी जावास्क्रिप्ट में लेक्सिकल स्कॉइंग नियम हैं, आंतरिक कार्य उन कार्यों के चर देख सकते हैं जिन्हें वे परिभाषित कर रहे हैं)।

thisMyObject कन्स्ट्रक्टर के स्थानीय दायरे के समान नहीं है।

आपने देखा है कि selfMyObject की this के लिए एक उपनाम है, और उस innerMethod अपने स्वयं के दायरे में this ओवरराइट किया है। फिर भी, this फ़ंक्शन स्कोप के लिए उपनाम नहीं है, न तो self.a और न ही this.a यहां कभी भी काम करेगा।

लेक्सिकल स्कोपिंग के एक और कठोर स्पष्टीकरण के लिए आप उदा। विकिपीडिया पर शुरू: http://en.wikipedia.org/wiki/Scope_(computer_science)

आप निष्पादन संदर्भों और ECMA में पहचानकर्ता संकल्प नियम मानक http://es5.github.com/#x10.3

+0

खैर समझाया देखें। :) – Kaeros

+0

मैं आपके तीसरे पैराग्राफ में 'फ़ंक्शन स्कोप' की बजाय ['VariableEnvironment'] (http://es5.github.com/#x10.3) शब्द को प्राथमिकता दूंगा, और यह बताता हूं कि पहले अनुच्छेद के पीछे कारण क्या जेएस [लेक्सिकल स्कोप] है (http://stackoverflow.com/questions/1047454/what-is-lexical-scope)। लेकिन बहुत अच्छी तरह से समझाया। –

+0

मैंने आपके कुछ बदलावों को शामिल किया है, लेकिन मैं फ़ंक्शन स्कोप के लिए वेरिएबल एंटरप्राइज़ का आदान-प्रदान करने में संकोच करता हूं। हालांकि यह तकनीकी रूप से अधिक सही है, मेरा मानना ​​है कि फ़ंक्शन स्कोप एक अवधारणा है जो अन्य भाषाओं से आने वाले प्रोग्रामर के लिए बेहतर है। मैंने ईसीएमए मानक में आपका लिंक जोड़ा है। – thebjorn

1

यह कार्यक्षेत्र के साथ एक समस्या है, जब कार्य बनाए जाते हैं तो वे अपने परिवेश (चर सहित) को बचाते हैं।

तो जब innerMethod बनाया गया है, तो यह self और a चर देख सकता है।

एक महत्वपूर्ण अवधारणा यह है कि जब कार्य घोषित किया जाता है, तो इसे कॉल करने के बजाए गुंजाइश बनाई जाती है।

आपके मामले में 1, b घोषित नहीं किया जा रहा है (यह वस्तु एक जैसी नहीं है)।

मामलों 5 और 6 में, आपने self.a नहीं बनाया था।

0

मुख्य कारण यह है कि self innerMethodके दायरे में this के बराबर नहीं है है के बारे में पढ़ सकते हैं। this फ़ंक्शन के मालिक को संदर्भित करने वाला एक कीवर्ड है।innerMethod लिए, यह एक उदाहरण विधि नहीं है, यह विंडो के अंतर्गत आता है।

function MyObject() { 
    var self = this; 

    var innerMethod = function() { 
     alert("inner method, self == this?: " + self == this); // false 
     alert("inner method: " + this); // [object Window] 
     alert("closest constructor name of in prototype chain ?: "+ this.__proto__.constructor.name); // Window 
    } 

    this.outerMethod = function(){ 
     innerMethod(); 
     alert("outer method: " + this); // [object MyObject] 
     alert("closest constructor name in prototype chain?: "+ this.__proto__.constructor.name); // MyObject 
    } 
} 

var o = new MyObject(); 
o.outerMethod(); 

आप here