2009-01-07 8 views
18

क्या आप कन्स्ट्रक्टर में और प्रोटोटाइप ऑब्जेक्ट के माध्यम से सेटिंग विधियों के बीच अंतर को समझा सकते हैं? निम्नलिखित कोड तरीकों की स्थापना के इन दो तरीकों से पता चलता - say_hello और say_bye दोनों ठीक से काम:प्रोटोटाइप ऑब्जेक्ट या कन्स्ट्रक्टर में अंतर के माध्यम से तरीकों को सेट करना, अंतर?

function MessageClass() { 
    this.say_bye = function() { alert('see ya'); }; 
} 

MessageClass.prototype.say_hello = function() { alert('hello'); }; 

x = new MessageClass(); 
x.say_hello(); 
x.say_bye(); 

उत्तर

31

फॉक्सक्स्ट्रोट और अन्नकाटा दोनों सही हैं, लेकिन मैं अपने 2 सेंट में फेंक दूंगा।

यदि आप प्रोटोटाइप का उपयोग करते हैं तो "संदेश क्लास" का प्रत्येक उदाहरण वास्तव में एक ही फ़ंक्शन का संदर्भ दे रहा है। कार्य केवल स्मृति में मौजूद हैं और सभी मामलों के लिए उपयोग किए जाते हैं। यदि आप प्रोटोटाइप के बजाय कन्स्ट्रक्टर में विधियों को घोषित करते हैं (या अन्यथा इसे एक विशिष्ट उदाहरण में जोड़ते हैं) तो MessageClass के प्रत्येक उदाहरण के लिए एक नया फ़ंक्शन बनाया जाता है।

कहा जा रहा है कि, ज्यादातर मामलों के लिए शायद कोई उल्लेखनीय प्रदर्शन अंतर नहीं है और यह संभावना नहीं है कि आप स्मृति उपयोग अंतर को देखेंगे। मैं प्रोटोटाइप विधि के साथ तब तक जाऊंगा जब तक आपके पास अन्यथा करने के लिए एक अनिवार्य कारण न हो। एकमात्र कारण यह है कि मैं कन्स्ट्रक्टर में एक विधि घोषित करना चाहूंगा कि अगर आपको बंद करने की आवश्यकता है। उदाहरण के लिए, आप ईवेंट हैंडलर्स है या आप getters/setters साथ निजी संपत्तियों अनुकरण करना चाहता था अगर आप यह कर सकते हैं:

function MessageClass() { 
    var self = this; 
    this.clickHander = function(e) { self.someoneClickedMe = true; }; 

    var _private = 0; 
    this.getPrivate = function() { return _private; }; 
    this.setPrivate = function(val) { _private = val; }; 
} 

संपादित करें: के बारे में क्योंकि वहाँ किया गया है चर्चा कैसे इस प्रभाव वस्तुओं कार्यों के साथ किसी अन्य वस्तु के लिए बढ़ा दी कन्स्ट्रक्टर में असाइन किया गया है मैं थोड़ा और विस्तार जोड़ रहा हूँ। मैं चर्चा को सरल बनाने के लिए "कक्षा" शब्द का उपयोग कर सकता हूं, लेकिन यह ध्यान रखना महत्वपूर्ण है कि जेएस कक्षाओं का समर्थन नहीं करता है (इसका मतलब यह नहीं है कि हम अच्छे ओओ विकास नहीं कर सकते हैं) या हम इस मुद्दे पर चर्चा नहीं करेंगे।

अधिकांश जावास्क्रिप्ट पुस्तकालय बेस क्लास और उप वर्ग पर निर्माता को कॉल करते हैं। (उदाहरण के लिए प्रोटोटाइप.जेएस का ऑब्जेक्ट.क्स्टेंड) इसका मतलब है कि प्रत्येक के कन्स्ट्रक्टर में असाइन किए गए तरीके परिणामस्वरूप ऑब्जेक्ट्स पर उपलब्ध होंगे। हालांकि, अगर आप वस्तुओं को विस्तारित कर रहे हैं तो अप्रत्याशित परिणाम हो सकते हैं।

अगर मैं MessageClass ऊपर लेने के लिए और यह विस्तार:

function ErrorMessageClass() {} 
ErrorMessageClass.prototype = new MessageClass(); 

errorMsg = new ErrorMessageClass(); 

फिर ERRORMSG उस पर एक getPrivate और setPrivate विधि है, लेकिन वे व्यवहार नहीं कर सकते हैं जैसा कि आप उम्मीद करेंगे। चूंकि उन कार्यों को स्कॉप्ड किया गया था जब उन्हें असाइन किया गया था (यानी "ErrorMessageClass.prototype = new MessageClass()" न केवल प्राप्त/सेट प्राइवेट विधियों को साझा किया जाता है, _private चर भी त्रुटि मैसेज क्लास के सभी उदाहरणों में साझा किया जाता है। यह अनिवार्य रूप से _private बनाता है ErrorMessageClass के लिए स्थैतिक संपत्ति।

var errorA = new ErrorMessageClass(); 
var errorB = new ErrorMessageClass(); 
errorA.setPrivate('A'); 
console.log(errorA.getPrivate()); // prints 'A' 
console.log(errorB.getPrivate()); // prints 'A' 
errorB.setPrivate('B'); 
console.log(errorA.getPrivate()); // prints 'B' 
इसी तरह clickHandler समारोह और someoneClickedMe संपत्ति के साथ

: उदाहरण के लिए:

errorA.clickHandler(); 
console.log(errorA.someoneClickedMe); // prints 'true' 
console.log(errorB.someoneClickedMe); // prints 'true' 

हालांकि, उन समारोह निर्धारण न तो बदल this._private उपयोग करने के लिए:

this.getPrivate = function() { return this._private; }; 
this.setPrivate = function(val) { this._private = val; }; 

और के उदाहरण के व्यवहार ErrorMessageClass आप जो अपेक्षा करेंगे उससे अधिक हो जाता है:

errorA.setPrivate('A'); 
errorB.setPrivate('B'); 
console.log(errorA.getPrivate()); // prints 'A' 
console.log(errorB.getPrivate()); // prints 'B' 
+0

आपको अपनी व्याख्या के लिए डर है :) (हालांकि मैं असहमत हूं कि कोई उल्लेखनीय अंतर नहीं है) – annakata

+0

हालांकि यदि आप इसका उपयोग करते हैं। _private, चर बाहर से सुलभ है। – Chris

+0

(तकनीकी रूप से बोलते हुए, आप किसी भी तरह से डीबगर के साथ किसी भी तरह से पता लगा सकते हैं, यदि नहीं, तो जेएस वातावरण) – Chris

5

अंतर नहीं है जब आप संदेश कक्षा से एक वर्ग निकाले जाते हैं। प्रोटोटाइप पर घोषित केवल विधियां संदेश के बाल वर्गों पर उपलब्ध होंगी।

+0

तो अगर मेरे पास 'BetterMessageClass.prototype = new MessageClass' केवल 'say_hello' विरासत में मिलेगा? – snitko

+0

मैं बाल वर्ग से "say_bye" विधि (जिसे "यह" के रूप में घोषित किया गया है) को कॉल करने में सक्षम हूं। यहां मेरा कोड है: फ़ंक्शन कर्मचारी() { this.say_bye = function() {चेतावनी ('देखें ya'); }; } फ़ंक्शन मैनेजर() { } प्रबंधक.प्रोटोटाइप = नया कर्मचारी; प्रबंधक.प्रोटोटाइप.कोनस्ट्रक्टर = प्रबंधक; var manager = new manager(); manager.say_bye(); – Raghav

+1

@foxxtrot यह सही नहीं है। कन्स्ट्रक्टर के अंदर 'इस' पर घोषित विधियां भी बाल वर्ग में उपलब्ध हैं। प्रेस्टॉल द्वारा कोड 'errorA.setPrivate (' ए ')' पर विचार करें, जो मूल वर्ग 'MessageClass' द्वारा' इस 'पर घोषित विधि तक पहुंच रहा है। – Suneel

6

यदि आप प्रोटोटाइप जेएस द्वारा विधियों को बाध्य करते हैं तो केवल इसे एक बार करना होगा और ऑब्जेक्ट क्लास से बांधना होगा (जो ओओ जेएस एक्सटेंशन के लिए इसे समझदार बनाता है)।

यदि आप "कक्षा" फ़ंक्शन के भीतर बाध्यकारी करते हैं, तो जेएस को प्रत्येक उदाहरण के लिए बनाने और असाइन करने का काम करना होगा।

+0

क्या यह एक प्रदर्शन समस्या है? –

+0

हां, सबसे निश्चित रूप से – annakata

+0

क्या होगा यदि मैं पहले funcations के रूप में विधियों को परिभाषित करता हूं, तो कन्स्ट्रक्टर में निम्न कहें: 'this.say_bye = MessageClass_sayhello; – snitko

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

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