2010-07-18 14 views
6

मैं कुछ समय के लिए एक परियोजना पर काम कर रहा था, यह पता लगाने की कोशिश कर रहा था कि मैं क्या गलत कर रहा था, जब मैंने आखिरकार "बग" को इस तथ्य से नीचे संकुचित कर दिया कि नीचे दिया गया कोड काम नहीं करता है:'यह' ऑब्जेक्ट को बिना किसी हैक के निजी जावास्क्रिप्ट फ़ंक्शंस में एक्सेस नहीं किया जा सकता है?

function Alpha() 
    { 
    this.onion = 'onion'; 

    function Beta() 
     { 
     alert(this.onion); 
     } 

    Beta(); 
    } 

alpha1 = new Alpha(); 
// Alerts 'undefined' 

हालांकि, अगर मैं इस के लिए कोड बदलने के लिए:

function Alpha() 
    { 
    var self = this; 
    this.onion = 'onion'; 

    function Beta() 
     { 
     alert(self.onion); 
     } 

    Beta(); 
    } 

alpha1 = new Alpha(); 
// Alerts 'onion' 

यह काम करता है जैसे मैं उम्मीद होती है। मेरे जीवन का एक बड़ा हिस्सा बर्बाद करने के बाद, क्या कोई यह समझा सकता है कि यह ऐसा क्यों काम करता है?

उत्तर

11

इस तरह काम करता है क्योंकि प्रत्येक फ़ंक्शन ने अपने निष्पादन संदर्भ से जुड़ा हुआ है।

समारोह आह्वान करने के लिए call या apply का उपयोग करना::

लेकिन वहाँ यह करने के लिए अन्य तरीकों से, उदाहरण के लिए कर रहे हैं

function Alpha() { 
    this.onion = 'onion'; 

    function Beta() { 
    alert(this.onion); 
    } 

    Beta.call(this); 
} 

var alpha1 = new Alpha(); 
// Alerts 'onion' 

नए ECMAScript 5 वें संस्करण स्टैंडर्ड, समारोह लागू करने के लिए एक तरह से परिचय संदर्भ, Function.prototype.bind विधि:

function Alpha() { 
    this.onion = 'onion'; 

    var Beta = function() { 
    alert(this.onion); 
    }.bind(this); 

    Beta(); 
} 

var alpha1 = new Alpha(); 
// Alerts 'onion' 

हम कह सकते हैं कि Beta फ़ंक्शन बाध्य है, और कोई फर्क नहीं पड़ता कि आप इसे कैसे कहते हैं, इसके this मान बरकरार रहेगा।

यह विधि अभी तक व्यापक रूप से समर्थित नहीं है, वर्तमान में केवल IE9pre3 में यह शामिल है, लेकिन आप इसे अब बनाने के लिए an implementation शामिल कर सकते हैं।

अब मुझे के बारे में कैसे काम करता है this विस्तृत करते हैं:

this मूल्य प्रत्येक execution context पर मौजूद हैं, और के लिए फंक्शन कोड परोक्ष जब एक समारोह कॉल किया जाता है, मूल्य निर्धारित किया जाता है सेट कर दिया जाता निर्भर करता है कि संदर्भ अगर का गठन किया।

अपने उदाहरण में, जब आप Beta(); आह्वान है, क्योंकि यह किसी भी वस्तु के लिए बाध्य नहीं है, हम कह सकते हैं संदर्भ कोई आधार वस्तु, तो, this मूल्य वैश्विक वस्तु के पास भेजेगा है।

अन्य मामले होता है जब आप उदाहरण के लिए एक समारोह है कि किसी वस्तु की संपत्ति के रूप में ही है आह्वान,:

var obj = { 
    foo: function() { return this === obj;} 
}; 
obj.foo(); // true 

आप देख सकते हैं, संदर्भ लागू किया जा रहा obj.bar(); एक आधार वस्तु है, जो obj होता है , और this आवंटित फ़ंक्शन के अंदर मूल्य इसका संदर्भ देगा।

नोट: reference type एक अमूर्त अवधारणा, भाषा कार्यान्वयन के उद्देश्य से आप कल्पना में विवरण देख सकते हैं के लिए परिभाषित किया गया है।

एक तिहाई मामले में जहां this मूल्य परोक्ष सेट कर दिया जाता है जब आप new ऑपरेटर का उपयोग, यह एक नव निर्मित वस्तु है कि इसके निर्माता के प्रोटोटाइप से विरासत का उल्लेख होगा:

function Foo() { 
    return this; // `this` is implicitly returned when a function is called 
}    // with `new`, this line is included only to make it obvious 

var foo = new Foo(); 
foo instanceof Foo; // true 
Foo.prototype.isPrototypeOf(foo); // true 
+0

+1। हमेशा के रूप में अच्छी तरह से। –

+0

धन्यवाद @ टिम! – CMS

2

जब आप एक गैर-सदस्य फ़ंक्शन को कॉल करते हैं (someObject.method() के रूप में नहीं कहा जाता है), यह विंडो के संदर्भ में चलता है। इससे कोई फर्क नहीं पड़ता कि यह एक निजी समारोह है या वैश्विक है।

आप कर सकता है:

call जबकि पहले तर्क के रूप में एक संदर्भ गुजर आप एक समारोह कॉल करने के लिए अनुमति देता है (apply समान है, लेकिन तर्क सूची एक सरणी है)।

हालांकि, मैं स्पष्ट नहीं हूं (यहां तक ​​कि मामूली उदाहरण के लिए) क्यों प्याज सार्वजनिक है लेकिन बीटा निजी है।

+0

लेकिन अगर मैंने किया: var Beta = function() {alert (self.onion);}, यह वही परिणाम देगा, भले ही बीटा एक निजी सदस्य हो। – Nick

+0

यह अभी भी एक सदस्य समारोह नहीं है। जावास्क्रिप्ट सदस्य फ़ंक्शन सार्वजनिक हैं। –

+0

हम्म .. ठीक है, शब्दावली के साथ भ्रमित हो रही है। लेकिन बीटा एक निजी सदस्य है (जिसका मूल्य एक फंक्शन है), सिर्फ सदस्य कार्य नहीं है? – Nick

8

JavaScript: The Definitive Guide, 5th Edition से (राइनो पुस्तक):

एक समारोह एक समारोह के रूप में के बजाय एक विधि के रूप में लागू किया जाता है, this कीवर्ड Glo को संदर्भित करता है बाल ऑब्जेक्ट। संदेहास्पद रूप से यह सच भी है जब एक नेस्टेड समारोह एक युक्त विधि कि एक विधि के रूप लागू किया गया था के भीतर ( एक समारोह के रूप में) शुरू हो जाती है: this कीवर्ड समारोह लेकिन (counterintuitively) को संदर्भित करता है जिसमें में एक मूल्य है नेस्टेड फ़ंक्शन के शरीर के भीतर वैश्विक वस्तु।

ध्यान दें कि this एक कीवर्ड है, परिवर्तनीय या संपत्ति का नाम नहीं है। जावास्क्रिप्ट सिंटैक्स आपको मान this पर असाइन करने की अनुमति नहीं देता है।

दो बातें यहाँ पर ध्यान देना:

  1. this एक चर नहीं है, इसलिए सामान्य बंद कब्जा नियम लागू नहीं होते।
  2. this प्रत्येक functiion कॉल पर, "एक सामान्य कार्य कॉल, या new के माध्यम से" रिबाउंड "है। चूंकि आप सामान्य फ़ंक्शन कॉल कर रहे हैं (बीटा को कॉल करते समय), this "वैश्विक ऑब्जेक्ट" से बाध्य हो रहा है।