2011-11-11 22 views
17

में 'इस' संदर्भ को संरक्षित करें this ऑब्जेक्ट के प्रोटोटाइप के अंदर संग्रहीत ईवेंट हैंडलर में जावास्क्रिप्ट संदर्भ को संरक्षित करने का सही तरीका क्या है? मैं '_this' या 'that' जैसे temp vars बनाने से दूर रहना चाहता हूं और मैं jQuery जैसे ढांचे का उपयोग नहीं कर सकता। मैंने देखा कि बहुत से लोग 'बाइंड' फ़ंक्शन का उपयोग करने के बारे में बात करते हैं लेकिन मेरे दिए गए परिदृश्य में इसे कार्यान्वित करने के बारे में अनिश्चित था।जावास्क्रिप्ट प्रोटोटाइप ईवेंट हैंडलर

var Example = function(foo,bar){ 
    this.foo = foo; 
    this.bar = bar; 
}; 
Example.prototype.SetEvent = function(){ 
    this.bar.onclick = this.ClickEvent; 
}; 
Example.prototype.ClickEvent = function(){ 
    console.log(this.foo); // logs undefined because 'this' is really 'this.bar' 
}; 

उत्तर

20

मैं bind() अब तक साफ समाधान किया जा रहा है लगता है:

this.bar.onclick = this.ClickEvent.bind(this); 

BTW अन्यthisthat प्रथा के अनुसार कहा जाता है बहुत बार।

+3

मैं * उस "(ला लाकॉकफ़ोर्ड) नामक संदर्भ बनाने से नफरत करता हूं। मैं "उदाहरण" (एक ला Stefanov), या "मुझे" (एक ला ExtJS) –

+4

वास्तव में, मुझे 'इस संदर्भ' बनाने से नफरत है, इससे कोई फर्क नहीं पड़ता कि वे कैसे नामित हैं। लेकिन सहमत हैं, 'वह' सबसे अच्छा नामकरण नहीं है। –

+1

मैं 'स्वयं' का उपयोग करता हूं, लेकिन हाल ही में पाया गया है कि वेबवर्कर्स में शीर्ष-स्तरीय संपत्ति के साथ एक नाम संघर्ष है। ऐसा नहीं है कि आपके पास एक ही नाम नहीं हो सकता है, लेकिन यह चीजों को भ्रमित करता है। साथ ही, मुझे 'यह' – Matt

7

bind पर बाहर MDN दस्तावेज़ की जांच: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

इस कार्यक्षमता का उपयोग करके आप गुंजाइश बदल सकते हैं (क्या this है):

Example.prototype.SetEvent = function(){ 
    this.bar.onclick = this.ClickEvent.bind(this); 
}; 

ध्यान रखें, हालांकि, कि यह एक नया है ईएमसीए को और इस प्रकार सभी उपयोगकर्ता एजेंटों में समर्थित नहीं हो सकता है। उपरोक्त लिंक किए गए एमडीएन दस्तावेज में एक पोलीफिल उपलब्ध है।

3

bind के साथ समस्या यह है कि only supported by IE9+ है।

समारोह es5-shim साथ polyfilled जा सकता है लेकिन यह पूरी तरह से देशी कार्यान्वयन के समान नहीं है:

  • चेतावनी: बाध्य समारोह एक प्रोटोटाइप संपत्ति है।
  • चेतावनी: बाध्य कार्य आपको arguments और caller गुणों में हेरफेर करने से रोकने के लिए बहुत मेहनत नहीं करते हैं।
  • चेतावनी: कन्स्ट्रक्टर के रूप में निष्पादित करने से बचने के लिए बाध्य कार्यों में call और apply में चेक नहीं हैं।

एक अन्य विकल्प jQuery.proxy हो सकता है:

$(elem).on('click', $.proxy(eventHandler, this)); 

यह और भी उपयोगी है यदि आप बाद में ईवेंट हैंडलर दूर करने के लिए है, क्योंकि एक समारोह proxy विधि, jQuery के माध्यम से चला जाता है जब चाहते हैं एक नया guid मान उत्पन्न करता है और उसके बाद उस कोर फ़ंक्शन के साथ-साथ परिणामी प्रॉक्सी फ़ंक्शन दोनों पर भी लागू होता है, ताकि आप किसी फ़ंक्शन द्वारा किए गए ईवेंट हैंडलर कॉलबैक को अनबिंड करने के लिए मूल फ़ंक्शन संदर्भ का उपयोग कर सकें:

$(elem).off('click', eventHandler); 
+0

'बाइंड () '$ .proxy' से कम पूर्ण क्रॉस-ब्राउज़र नहीं है। यह मूल रूप से '.bind()' का एक गैर-मानक संस्करण है। यदि आपके द्वारा सूचीबद्ध चेतावनी वास्तव में एक चिंता है, तो '$ .proxy' कोई बेहतर नहीं होगा। उल्लेख नहीं है कि सवाल स्पष्ट है कि वह jQuery का उपयोग नहीं कर सकता है। –

+0

@ स्क्विंट मैं '$ .proxy' (या एक समान कार्यान्वयन) का उपयोग करने का सुझाव दे रहा हूं क्योंकि यह एक ढीला कनेक्शन है, और ओओ इवेंट हैंडलिंग में यह वास्तव में उपयोगी है। लेकिन धन्यवाद, मैं अपना जवाब अपडेट करूंगा क्योंकि, जैसा कि आप कह रहे हैं, एक पॉलीफ़िल्ल्ड '.bind()' '$ .proxy' से कम पूर्ण क्रॉस-ब्राउज़र नहीं है। –

0

अन्य समाधान: ईएस 6 द्वारा पेश किए गए "तीर कार्यों" का उपयोग करें। उनके पास संदर्भ बदलने के लिए विशिष्टता नहीं है, आईई this अंक।

function Foo(){ 
    myeventemitter.addEventListener("mousedown", (()=>{ 
     return (event)=>{this.myinstancefunction(event)}; /* Return the arrow 
function (with the same this) that pass the event to the Foo prototype handler */ 
    })()); 
} 
Foo.prototype.myinstancefunction = function(event){ 
    // Handle event in the context of your Object 
} 

Arrow function specs @ MDN

संपादित

इसके साथ सावधान रहें: यहाँ एक उदाहरण है। यदि आप इसे क्लाइंट-साइड का उपयोग करते हैं और आप जेएस दुभाषिया की क्षमताओं के बारे में सुनिश्चित नहीं हो सकते हैं, तो ध्यान दें कि पुराना ब्राउज़र तीर फ़ंक्शंस (see CanIUse stats) को पहचान नहीं पाएगा। इस विधि का उपयोग केवल तभी करें जब आप जानते हैं कि यह क्या चलाएगा (हाल ही के ब्राउज़र केवल & नोडजेएस ऐप्स)

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