2011-01-27 24 views
17

मैं this कीवर्ड का उपयोग करके बनाए गए ऑब्जेक्ट शब्दशः के भीतर एक फ़ंक्शन कॉल करने का प्रयास कर रहा हूं।जावास्क्रिप्ट ऑब्जेक्ट में एक फ़ंक्शन को कॉल करना शाब्दिक नोटेशन घोषणा

window.onload = function(){ 

    var animBtn = document.getElementById('startAnim'); 

    animBtn.addEventListener('click', Animation.init, false); 

} 

var Animation = { 
    init: function(){ 

    this.doTheMove(); // I'm calling the function here, but it gives an error. 

    }, 
    doTheMove: function(){ 

    alert('Animation!'); 

    } 
} 

क्यों कोई त्रुटि हुई: लेकिन एक त्रुटि कह this.doTheMove() कार्य नहीं है दिखाता है?

उत्तर

16

क्या हो रहा है की एक व्याख्या। प्वाइंट का जवाब अच्छा है लेकिन मैं इसे अधिक सामान्य रूप से समझाऊंगा। this पर एक बहुत अच्छा शोध here

एक ईवेंट हैंडलर केवल कॉलबैक है। आप इसे एक समारोह और सुनने के लिए एक घटना पास करते हैं। अंततः यह सब उस काम को कॉल करेगा।

Animation.init केवल उस फ़ंक्शन के लिए एक गेटर है। इस तरह यह के बारे में सोचो:

var callback = Animation.init 
animBtn.addEventListener('click', callback, false); 
... 
// internal browser event handler 
handler() { 
    // internal handler does stuff 
    ... 
    // Oh click event happened. Let's call that callback 
    callback(); 
} 

तो आपके द्वारा किए गए जावास्क्रिप्ट this === window में

var callback = function(){ 
    this.doTheMove(); // I'm calling the function here, but it gives an error. 
} 

में पारित हो जाता है डिफ़ॉल्ट रूप से। यह वैश्विक वस्तु को संदर्भित करेगा यदि यह किसी चीज़ पर सेट नहीं है। शुद्ध प्रभाव यह है कि window.doTheMove कहा जाता है। और वह कार्य मौजूद नहीं है।

इस मामले में callback के बाद से actaully एक घटना से पुकारा जाता है डोम उद्देश्य यह है कि अपने फोन node.doTheMove जो अभी भी अस्तित्व में नहीं है तो ईवेंट को ट्रिगर करने में this वस्तु अंक हैंडलर।

आप जो करना चाहते थे उसे एनीमेशन के संदर्भ में लपेटना है।

var callback = function() { 
    Animation.init(); 
} 

यह एक समारोह निष्पादन है और यह Animation पर init निष्पादित करता है। जब आप इसे किसी ऑब्जेक्ट पर निष्पादित करते हैं तो आंतरिक रूप से this === Animation जैसा कि आप उम्मीद करेंगे।

समेट करने के लिए। यहां मुद्दा यह है कि Animation.init केवल एक फ़ंक्शन का संदर्भ है। इसके बारे में कोई जानकारी नहीं है जैसे पॉइंटी ने उल्लेख किया है।

+3

आपका उत्तर अधिकतर सही है (अंतिम परिणाम में बिल्कुल सही)। केवल गलती है * "शुद्ध प्रभाव वह खिड़की है .doTheMove कहा जाता है।" *। चूंकि 'init'' addEventListener' को पास किया गया है, इसे वास्तव में 'एनिमबटन' तत्व के संदर्भ से बुलाया जा रहा है, इसलिए 'this.doTheMove()' प्रभावी रूप से 'animBtn.doTheMove()' है। फिर, अंतिम परिणाम वही है। बस एक मामूली जानकारी। – user113716

+0

@patrickdw धन्यवाद मुझे यकीन नहीं था कि यह 'डीओएम ऑब्जेक्ट या विंडो ऑब्जेक्ट के रूप में पारित किया गया था या नहीं। मैं पुष्टि करने के लिए परीक्षण करने के लिए परेशान नहीं किया था। मुझे बहुत उम्मीद थी। – Raynos

+1

+1 और निष्पक्ष होने के लिए, 'यह' का आपका मूल्यांकन सही होगा यदि यह माइक्रोसॉफ्ट के' अटैचमेंट 'का उपयोग किया जा रहा था क्योंकि यह (कुछ कारणों से) हैंडलर के संदर्भ को सेट नहीं करता है। – user113716

10

आप जिस तरह से आप सेट बदलना होगा अप:

window.onload = function(){ 

    var animBtn = document.getElementById('startAnim'); 

    animBtn.addEventListener('click', function() { Animation.init(); }, false); 

} 

जावास्क्रिप्ट, वास्तव में एक समारोह एक वस्तु शाब्दिक के हिस्से के रूप में परिभाषित किया जा करने के लिए होता है कि बहुत ज्यादा वास्तव में मतलब यह नहीं है (में अगर कुछ भी , असल में)। Animation.initका संदर्भ आपको उचित फ़ंक्शन पर ले जाता है, लेकिन समस्या यह है कि जब फ़ंक्शन बाद में लागू किया जाता है (वास्तविक "क्लिक" के जवाब में) ब्राउज़र ब्राउज़र को कॉल करता है लेकिन उसे पता नहीं है कि ऑब्जेक्ट "एनीमेशन "this संदर्भ होना चाहिए। फिर, तथ्य यह है कि इस उद्देश्य को वस्तु के हिस्से के रूप में घोषित किया गया था, यहां पर कोई महत्व नहीं है। इसलिए, यदि आप this चाहते हैं तो अपने स्वयं के चयन में कुछ खास हो, तो आपको यह सुनिश्चित करना होगा कि यह आपके द्वारा नियंत्रित कोड में स्पष्ट रूप से सेट हो। उपर्युक्त समाधान इसे करने का सबसे आसान तरीका है: यह "क्लिक" घटनाओं को एक अज्ञात फ़ंक्शन के साथ संभालता है जो "एनीमेशन" के माध्यम से एक स्पष्ट संदर्भ के माध्यम से "init" फ़ंक्शन को आमंत्रित करने के अलावा कुछ भी नहीं करता है। यह सुनिश्चित करेगा कि this "init" ऑब्जेक्ट को संदर्भित करता है जब "init" चलता है।

"() .bind" सुविधा एक अन्य विकल्प का उपयोग किया जाएगा कि कुछ ब्राउज़र और चौखटे का समर्थन:

window.onload = function(){ 

    var animBtn = document.getElementById('startAnim'); 

    animBtn.addEventListener('click', Animation.init.bind(Animation); }, false); 

} 

शुद्ध प्रभाव लगभग बिल्कुल वैसा ही है: कि कॉल के लिए ".bind()" एक फ़ंक्शन देता है जो उस फ़ंक्शन को आमंत्रित करता है जिस पर इसे "एनीमेशन" ऑब्जेक्ट में "init" फ़ंक्शन कहा जाता है), और this संदर्भ ("संदर्भ" ऑब्जेक्ट) के रूप में इसके पहले तर्क के साथ ऐसा करता है। यह वही बात है जिसे हम पहले उदाहरण से प्राप्त करते हैं, या प्रभावी रूप से वैसे भी।

+0

अधिक जानकारी में समझाएं कि एनीमेशन.init फ़ंक्शन पॉइंटर को कैसे गुजर रहा है और इसे कॉल करना इसे 'इस' ऑब्जेक्ट के साथ आमंत्रित करता है जो 'एनीमेशन' नहीं है। समाधान अच्छा है, लेकिन स्पष्टीकरण क्यों पहली जगह में विफल रहता है इसकी कमी है। – Raynos

+0

@ रेनोस हाँ आप सही हैं, मैं इसका वर्णन करने के लिए कुछ पाठ जोड़ूंगा। – Pointy

+0

आपके उत्तर के लिए धन्यवाद, मैं अब परीक्षण करूंगा – Shaoz

0

आप portotype आधार दृष्टिकोण का उपयोग करना चाह सकते हैं:

// generate a prototype object which can be instantiated 
var Animation = function() { this.doTheMove(); } 
Animation.prototype.doTheMove = function() { 
    // if the object has only one method, the whole code could be moved to 
    // var Animation = function() {...} above 
    alert('Animation!'); 
} 

Animation.prototype.otherMethod = function(param1, param2) { 
    // ... 
} 


// run the code onload 
window.onload = function(){ 
    var animBtn = document.getElementById('startAnim'); 
    animBtn.addEventListener('click', new Animation(), false); 
} 
+3

यह सही नहीं है। 'AddEventListener' को एक फ़ंक्शन प्राप्त करने की आवश्यकता है। आप एक ऑब्जेक्ट पास कर रहे हैं जो फ़ंक्शन का संदर्भ देता है। – user113716

+0

सही! मेरा जवाब गलत है, श्रीमान। – Spliffster

1

मुझे लगता है कि यह एक और अच्छा तरीका है, मुझे लगता है।

window.onload = function(){ 

    var animBtn = document.getElementById('startAnim'); 

    animBtn.addEventListener('click', Animation.init, false); 

}; 

var Animation = { 
    init: function(){ 

     Animation.doTheMove(); // This will work, but your IDE may complain... 

    }, 
    doTheMove: function(){ 

     alert('Animation!'); 

    } 
}; 
0

साढ़े सालों बाद, लेकिन मुझे आशा है कि मेरा उत्तर वर्तमान और भविष्य के डेवलपर्स के लिए कुछ अंतर्दृष्टि भी प्रदान कर सकता है।

मैं स्वयं परिभाषित कार्यों के अंदर शाब्दिक वस्तुओं का उपयोग करके कोड करता हूं, और पोस्ट किया गया मूल प्रश्न ठीक काम करता है यदि एक और आत्म-निष्पादन कार्य एक प्रयास और पकड़ विवरण के साथ जोड़ा जाता है।

यह इंगित करना बहुत महत्वपूर्ण है कि यह सब कुछ दायरे और संदर्भ के बारे में है।

कृपया किसी भी कमी को सही करें या इस विधि का उपयोग करने के अधिक प्रभावी सुझाव प्रदान करें।

(function() { 

console.log(this); // window object 

    var animation = { 
     init: function() { 
      this.doTheMove(); 
     }, 
     doTheMove: function() { 
      alert("Animation"); 
      console.log(animation); // animation object 
     } 
    }; 

    (function() { 
     try { 
      console.log("animation.init"); // animation.init function 
      animation.init(); 
     } catch(e) { 
      console.log("Error is: " + e); 
     } 
    })(); 

})(); 
संबंधित मुद्दे