2012-05-08 11 views
13

, इस कोड हैजावास्क्रिप्ट OOP: के साथ या "प्रोटोटाइप" बिना विधि परिभाषा

function Person() { 
    function myMethod() { 
     alert ('hello'); 
    } 
    this.method = myMethod; 
} 

बराबर करने के लिए:

function Person() { } 
Person.prototype.method2 = function() { 
    alert ('hello'); 
}; 

यदि हाँ, जो विधि परिभाषा का उपयोग करना चाहिए और क्यों?

+1

जावास्क्रिप्ट में 'प्रोटोटाइप' बनाम 'यह' का संभावित डुप्लिकेट?] (Http://stackoverflow.com/questions/310870/use-of-prototype-vs-this-in-javascript) –

+0

[ प्रोटोटाइप में कन्स्ट्रक्टर फ़ंक्शन बनाम में जावास्क्रिप्ट ऑब्जेक्ट विधि घोषित करना] (http://stackoverflow.com/questions/9772307/declaring-javascript-object-method-in-constructor-function-vs-in-prototype) –

उत्तर

13

वे आपके सरल उदाहरण में कार्यात्मक रूप से समकक्ष हैं, लेकिन दृश्यों के पीछे बहुत अलग तरीके से काम करते हैं। एक समारोह पर prototype संपत्ति वास्तव में "प्रोटोटाइप टेम्पलेट" है। यह कहता है "जब भी कोई ऑब्जेक्ट बनाया जाता है और मुझे ऑब्जेक्ट के कन्स्ट्रक्टर के रूप में उपयोग किया जाता है, तो उन्हें इस ऑब्जेक्ट को उनके प्रोटोटाइप के रूप में दें"।

तो आपके दूसरे उदाहरण में बनाए गए सभी Person एस method2 विधि की एक ही प्रति साझा करते हैं।

पहले उदाहरण में, प्रत्येक बार दुभाषिया function कीवर्ड से मुकाबला करता है, तो यह एक नया फ़ंक्शन ऑब्जेक्ट बनाता है। तो पहले उदाहरण में, Person के प्रत्येक उदाहरण में myMethod विधि की अपनी प्रति है। इस समय का अधिकांश हिस्सा इससे कोई फर्क नहीं पड़ता। लेकिन यह पहला दृष्टिकोण अधिक स्मृति का उपयोग करता है, और कभी-कभी इससे कोई फर्क पड़ता है।

वे अधिक दिलचस्प मामलों में कार्यात्मक रूप से समकक्ष नहीं हैं। पहले उदाहरण में, myMethodPerson में परिभाषित स्थानीय चरों तक पहुंच सकता है, लेकिन दूसरा उदाहरण एक अंतर के रूप में नहीं हो सकता है।

+0

क्या आप जानते हैं एक मामला/संदर्भ जहां पहली विधि अधिक उपयोगी होगी? धन्यवाद। –

+2

पहली स्थिति आपको "निजी" चर रखने की अनुमति देती है। 'व्यक्ति' विधि में परिभाषित किसी भी स्थानीय चर को 'myMethod' द्वारा एक्सेस किया जा सकता है, लेकिन कुछ भी नहीं। मैं क्रॉकफोर्ड के * जावास्क्रिप्ट गुड पार्ट्स * को पढ़ने की सलाह देता हूं, क्योंकि वह इस पैटर्न में बहुत विस्तार से जाता है। –

0

नहीं, वे बराबर नहीं हैं। हालांकि, वे समान हैं। पहली विधि प्रत्येक new Person() के लिए एक नया फ़ंक्शन myMethod बनाएगी।

दूसरी विधि में एक फ़ंक्शन method2 होगा जो सभी Person's द्वारा "साझा" किया जाएगा।

2

पहले परिदृश्य में, जब आप एक नया व्यक्ति बनाते हैं, var person1 = new Person();, इसकी अपनी प्रति myMethod होगी। यदि आप 100 व्यक्ति वस्तुओं को बनाते हैं, तो प्रत्येक के पास इस विधि की अपनी प्रतिलिपि होगी।

प्रोटोटाइप का उपयोग करके, प्रत्येक नई व्यक्ति वस्तु विधि परिभाषा साझा करेगी। यह बहुत अधिक मेमोरी कुशल है क्योंकि विधि की केवल एक प्रति होगी।

यदि आप कई व्यक्ति वस्तुओं को रखने की योजना बना रहे हैं, तो दूसरा तरीका बेहतर है .. लेकिन अगर केवल कुछ व्यक्ति वस्तुएं हैं, तो इससे कोई फर्क नहीं पड़ता।

+0

यदि गैर-प्रोटोटाइप विधि लोकप्रिय हो गई है, तो शायद जावास्क्रिप्ट रनटाइम अंतर को दूर कर देगा ... –

+0

मुझे निश्चित रूप से गैर-प्रोटोटाइप विधि अधिक पठनीय मिलती है। – Kokodoko

0

वे इसी तरह की सुविधा है, लेकिन आपको दूसरा दृष्टिकोण (प्रोटोटाइप) का उपयोग करना चाहिए, क्योंकि जब आप एक वस्तु new Person() हर वस्तु का उपयोग कर एक ही method2 साझा करेंगे, लेकिन पहले दृष्टिकोण का उपयोग कर पैदा करेगा प्रत्येक नई वस्तु होगा यह खुद है myMethod() की खपत होगी कि मो स्मृति

कुछ दिन पहले मैंने एक समान प्रश्न पूछा औरthis answer मिला।

1

यह पूरी तरह से समकक्ष नहीं है।

दोनों मामलों में, आप वैश्विक नामस्थान में एक फ़ंक्शन (कन्स्ट्रक्टर) Person() परिभाषित करते हैं।

पहले मामले में, आप Person() फ़ंक्शन के अंदर बंद होने पर एक नया फ़ंक्शन myMethod() परिभाषित करते हैं। आम तौर पर, myMethod() फ़ंक्शन फ़ंक्शन/कन्स्ट्रक्टर Person() समाप्त होने के बाद उपलब्ध नहीं होगा। हालांकि, इस मामले में आप इसे this.method पर असाइन करें। इस प्रकार, जब आप निर्माता

var myPerson = new Person(); 

एक नई वस्तु बनाई गई है चलाने के लिए, तो Person() समारोह नई वस्तु को this सेट के साथ कहा जाता है। इसलिए, आपकी नई ऑब्जेक्ट method फ़ील्ड myMethod फ़ंक्शन से जुड़ी है।

दूसरे मामले में, method2Person.prototype के अंदर परिभाषित किया गया है। इस मामले में, आप जब फोन

var myPerson = new Person(); 

कोई क्षेत्र अपने नए ऑब्जेक्ट के अंदर सीधे परिभाषित किया जाएगा (जैसा कि आप समारोह Person में this साथ कुछ भी नहीं)। हालांकि, प्रत्येक वस्तु में इसके प्रोटोटाइप का संदर्भ होता है। यदि ऑब्जेक्ट Person() पर कॉल करके बनाया गया है, तो यह संदर्भ Person.prototype पर सेट है। इस प्रकार, आपकी ऑब्जेक्ट में अंततः method2 होगा, हालांकि सीधे स्वयं में नहीं, बल्कि प्रोटोटाइप में। तो जब आप

myPerson.method2(); 

फोन दुभाषिया myPerson ऑब्जेक्ट के अंदर method2 के लिए लग रहा है और कुछ भी नहीं पाता है, तो यह, myPerson के प्रोटोटाइप है, जो Person.prototype है और method2 पाता में लग रहा है, तो यह यह कहता है।

लंबी कहानी छोटी: पहले आपके कन्स्ट्रक्टर विधि बनाता है, इसलिए हर बार जब आप कन्स्ट्रक्टर को कॉल करते हैं, तो नई ऑब्जेक्ट में एक नई विधि बनाई जाती है और डाली जाती है। दूसरे मामले में, विधि प्रोटोटाइप में संग्रहीत होती है, इसलिए आपके द्वारा बनाए गए प्रत्येक ऑब्जेक्ट में आपकी विधि के उसी उदाहरण का संदर्भ होगा।

+0

लुकअप के कारण, प्रदर्शन के अनुसार पहली विधि तेज होगी? –

+1

@ जीन-फिलिप मार्टिन हां। आपको तेज विधि लुकअप मिलता है, लेकिन अधिक मेमोरी उपयोग होता है। लंबे अंतर प्रोटोटाइप श्रृंखला के साथ दोहराए गए कॉल पर प्रदर्शन अंतर दिखाई देना चाहिए। इस साधारण मामले में, हालांकि, चिंता करने की शायद कुछ भी नहीं है। – Imp

+0

मेरे पास दृष्टिकोण की प्रदर्शन तुलना के लिए परीक्षण करने के लिए यहां एक परीक्षण केस है: http://jsperf.com/method-definition-with-or-without-prototype –

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