2009-05-21 33 views
162

में प्रोटोटाइप विरासत को समझना मैं जावास्क्रिप्ट ओओपी के लिए नया हूं। क्या आप कोड के निम्नलिखित ब्लॉक के बीच अंतर को समझा सकते हैं। मैंने परीक्षण किया और दोनों ब्लॉक काम करते हैं। सबसे अच्छा अभ्यास क्या है और क्यों?जावास्क्रिप्ट

पहले ब्लॉक:

function Car(name){ 
    this.Name = name; 
} 

Car.prototype.Drive = function(){ 
    document.write("My name is " + this.Name + " and I'm driving. <br />"); 
} 

SuperCar.prototype = new Car(); 
SuperCar.prototype.constructor = SuperCar; 

function SuperCar(name){ 
    Car.call(this, name); 
} 

SuperCar.prototype.Fly = function(){ 
    document.write("My name is " + this.Name + " and I'm flying! <br />"); 
} 

var myCar = new Car("Car"); 
myCar.Drive(); 

var mySuperCar = new SuperCar("SuperCar"); 
mySuperCar.Drive(); 
mySuperCar.Fly(); 

दूसरा ब्लॉक:

function Car(name){ 
    this.Name = name; 
    this.Drive = function(){ 
     document.write("My name is " + this.Name + " and I'm driving. <br />"); 
    } 
} 

SuperCar.prototype = new Car(); 

function SuperCar(name){ 
    Car.call(this, name); 
    this.Fly = function(){ 
     document.write("My name is " + this.Name + " and I'm flying! <br />"); 
    } 
} 

var myCar = new Car("Car"); 
myCar.Drive(); 

var mySuperCar = new SuperCar("SuperCar"); 
mySuperCar.Drive(); 
mySuperCar.Fly(); 

क्यों लेखक prototype का उपयोग कर Drive और Fly विधियों को जोड़ने था, लेकिन Car वर्ग और this.Fly अंदर this.Drive पद्धति के रूप में उन्हें घोषित नहीं करती है SuperCar कक्षा में?

SuperCar.prototype.constructor को SuperCar पर वापस सेट करने की आवश्यकता क्यों है? prototype सेट होने पर कन्स्ट्रक्टर प्रॉपर्टी ओवरराइड है? मैंने इस लाइन पर टिप्पणी की और कुछ भी नहीं बदला।

SuperCar कन्स्ट्रक्टर में Car.call(this, name); क्यों कॉल करें? नहीं होगा गुणों और Car के तरीकों 'विरासत में मिला' किया जब मैं

var myCar = new Car("Car"); 
+3

अधिक आधुनिक तरीका Object.create करने के लिए उपयोग (है) नए की बजाय: http://ncombo.wordpress.com/2013/07/11/javascript-inheritance-done-right/ – Jon

+2

बस एक नोट यह उदाहरण भ्रमित हो सकता है: इस मामले में 'सुपर' एक उड़ान कार को संदर्भित करता है, जबकि ओओपी में 'सुपर' आमतौर पर पैरेंट प्रोटोटाइप/कक्षा को संदर्भित करता है। – mikemaccana

+2

मुझे लगता है कि वह हिस्सा जो जावास्क्रिप्ट के प्रोटोटाइपिकल विरासत को समझने में मुश्किल बनाता है वह यह है कि यह इसे एक निर्माता के साथ मिश्रित करता है। क्या होगा अगर हम निर्माता और वर्ग के विचार को हटा दें, और हमारे पास केवल वस्तुएं हैं। प्रत्येक वस्तु या तो कुछ भी (शून्य) या किसी अन्य वस्तु से विरासत में प्राप्त होती है। यह समझना बहुत आसान होगा, और यह वही है जो Object.create() करते हैं। –

उत्तर

78

दो ब्लॉकों एक तरीका है कि पहले उदाहरण में Drive() केवल एक बार उपलब्ध नहीं होगा, जबकि दूसरा दृष्टिकोण पर Drive() उदाहरण प्रति उपलब्ध नहीं होगा में मतभेद है (हर बार जब आप new Car() कर समारोह drive() फिर से बनाया जाएगा)। या अलग-अलग ने कहा कि पहले फ़ंक्शन को स्टोर करने के लिए प्रोटोटाइप का उपयोग करता है और दूसरा कन्स्ट्रक्टर। कार्यों के लिए लुकअप कन्स्ट्रक्टर और फिर प्रोटोटाइप है। तो Drive() के अपने लुकअप के लिए यह कन्स्ट्रक्टर या प्रोटोटाइप में है, भले ही यह इसे ध्यान में रखे। प्रोटोटाइप का उपयोग करना अधिक कुशल है क्योंकि आम तौर पर आपको प्रति प्रकार केवल एक बार फ़ंक्शन की आवश्यकता होती है।

new जावास्क्रिप्ट में कॉल स्वचालित रूप से प्रोटोटाइप में निर्माता को सेट करता है। यदि आप प्रोटोटाइप को ओवरराइट कर रहे हैं तो आपको कन्स्ट्रक्टर मैन्युअल रूप से सेट करना होगा।

जावास्क्रिप्ट में विरासत में super जैसी कोई चीज़ नहीं है। तो यदि आपके पास उप-वर्ग है तो सुपर कन्स्ट्रक्टर को कॉल करने का एकमात्र मौका इसके नाम से है।

1

मैं 100% यकीन है कि नहीं हूँ, लेकिन मेरा मानना ​​है कि अंतर यह है कि दूसरे उदाहरण बस सुपरकार में कार वर्ग की सामग्री डुप्लिकेट है ऑब्जेक्ट, जबकि पहली बार सुपर क्लायर प्रोटोटाइप को कार क्लास से लिंक करता है, ताकि कार क्लास में रन-टाइम परिवर्तन सुपरकायर क्लास को भी प्रभावित कर सकें।

136

Norbert Hartl's answer में जोड़ने के लिए, SuperCar.prototype.constructor की आवश्यकता नहीं है, लेकिन कुछ लोग इसे किसी ऑब्जेक्ट के निर्माण कार्य (इस मामले में सुपरकार ऑब्जेक्ट) प्राप्त करने के सुविधाजनक तरीके के रूप में उपयोग करते हैं।

बस पहले उदाहरण से, Car.call (यह नाम) सुपरकार निर्माता समारोह में है, क्योंकि जब आप ऐसा करते हैं:

  1. एक:

    var mySuperCar = new SuperCar("SuperCar"); 
    

    यह वही जावास्क्रिप्ट करता है ताजा, खाली वस्तु तत्काल है।

  2. ताजा ऑब्जेक्ट का आंतरिक प्रोटोटाइप कार पर सेट है।
  3. सुपरकार कन्स्ट्रक्टर फ़ंक्शन चलाता है।
  4. समाप्त वस्तु वापस आ गई है और mySuperCar में सेट है।

ध्यान दें कि जावास्क्रिप्ट ने आपके लिए कार क्यों नहीं कहा। प्रोटोटाइप के रूप में वे हैं, किसी भी संपत्ति या विधि जिसे आप सुपरकायर के लिए सेट नहीं करते हैं, कार में देखा जाएगा। कभी-कभी यह अच्छा होता है, उदा। सुपरकार में ड्राइव विधि नहीं है, लेकिन यह कार की एक साझा कर सकती है, इसलिए सभी सुपरकार्स एक ही ड्राइव विधि का उपयोग करेंगे। अन्य बार आप साझा नहीं करना चाहते हैं, जैसे प्रत्येक सुपरकायर का अपना नाम होता है। तो प्रत्येक सुपरकार के नाम को अपनी खुद की चीज़ में कैसे सेट करने के बारे में कोई जाता है? आप this.Name सुपरकार निर्माता समारोह के अंदर सेट कर सकते हैं:

function SuperCar(name){ 
    this.Name = name; 
} 

यह काम करता है, लेकिन एक दूसरे प्रतीक्षा करें। क्या हमने कार निर्माता में बिल्कुल वही काम नहीं किया? खुद को दोहराना नहीं चाहते हैं। चूंकि कार पहले से ही नाम सेट करती है, चलो बस इसे कॉल करें।

function SuperCar(name){ 
    this = Car(name); 
} 

ओह, आप कभी नहीं विशेष this वस्तु संदर्भ बदलना चाहते हैं। 4 कदम याद रखें? उस ऑब्जेक्ट पर लटकाएं जो जावास्क्रिप्ट ने आपको दिया है, क्योंकि यह आपके सुपरकार ऑब्जेक्ट और कार के बीच कीमती आंतरिक प्रोटोटाइप लिंक रखने का एकमात्र तरीका है। तो हम अपने आप को दोहराने के बिना नाम कैसे सेट करते हैं और हमारे ताजा सुपरकार ऑब्जेक्ट को फेंकने के बिना जावास्क्रिप्ट ने हमारे लिए तैयार करने के लिए इतना खास प्रयास किया है?

दो चीजें। एक: this का अर्थ लचीला है। दो: कार एक समारोह है। कार को कॉल करना संभव है, न कि एक प्राचीन, ताजा तत्काल वस्तु के साथ, बल्कि इसके बजाय, एक सुपरकार ऑब्जेक्ट कहें। यही कारण है कि हमें अंतिम समाधान है, जो अपने प्रश्न में पहला उदाहरण का हिस्सा है देता है:

function SuperCar(name){ 
    Car.call(this, name); 
} 

एक समारोह के रूप में, कार के साथ लागू किया जा करने के लिए अनुमति दी है समारोह के call method है, जो करने के लिए कार के भीतर this के अर्थ बदल जाता है सुपरकार उदाहरण हम निर्माण कर रहे हैं। Presto! अब प्रत्येक सुपरकार को अपना नाम संपत्ति मिलती है।

सुपरकायर कन्स्ट्रक्टर में Car.call(this, name) लपेटने के लिए प्रत्येक नई सुपरकायर ऑब्जेक्ट को अपनी अनूठी नाम संपत्ति देता है, लेकिन कोड में पहले से मौजूद कोड को डुप्लिकेट किए बिना।

प्रोटोटाइप डरावना नहीं हैं जब आप उन्हें समझते हैं, लेकिन वे क्लासिक क्लास/विरासत ओओपी मॉडल की तरह नहीं हैं। मैंने the prototypes concept in JavaScript के बारे में एक लेख लिखा था। यह एक गेम इंजन के लिए लिखा गया है जो जावास्क्रिप्ट का उपयोग करता है, लेकिन यह फ़ायरफ़ॉक्स द्वारा उपयोग किया जाने वाला एक ही जावास्क्रिप्ट इंजन है, इसलिए यह सभी प्रासंगिक होना चाहिए। उम्मीद है की यह मदद करेगा।

+4

"SuperCar.prototype.constructor" की आवश्यकता है यदि आप ' – Raynos

+3

काम करने के लिए लीगेसी इंजनों में ऑब्जेक्ट .getPrototypeOf' अनुकरण "जावास्क्रिप्ट में प्रोटोटाइप अवधारणा" का वर्तमान लिंक टूटा हुआ है। क्या कोई और जगह है जहां मैं इस लेख को पढ़ सकता हूं? – shockawave123

8

नॉरबर्ट, आपको ध्यान रखना चाहिए कि आपका पहला उदाहरण डगलस क्रॉकफोर्ड को स्यूडोक्लासिकल विरासत कहता है। कुछ बातें इस बारे में गौर करने योग्य

  1. आप कार निर्माता दो बार, एक बार SuperCar.prototype = नई कार() लाइन और अन्य से "निर्माता चोरी" लाइन Car.call (इस से फोन करेगा .. । आप इसके बजाय प्रोटोटाइप प्राप्त करने के लिए एक सहायक विधि बना सकते हैं और आपके कार कन्स्ट्रक्टर को केवल सेटअप को और अधिक कुशल बनाने के बाद ही चलाना होगा।
  2. SuperCar.prototype.constructor = सुपरकार लाइन आपको कन्स्ट्रक्टर की पहचान करने के लिए उदाहरण का उपयोग करने की अनुमति देगी। कुछ लोग यह चाहते हैं कि
  3. संदर्भ वर्र्स जैसे: var arr = ['one', 'two'] सुपर (उदाहरण के लिए कार) पर परिभाषित होने पर सभी उदाहरणों से साझा किया जाएगा। इसका मतलब है inst1.arr। पु sh ['three'], inst2.arr.push ['four'], आदि, सभी उदाहरणों के लिए दिखाए जाएंगे!अनिवार्य रूप से, स्थिर व्यवहार जो आप शायद नहीं चाहते हैं।
  4. आप दूसरा ब्लॉक कन्स्ट्रक्टर में फ्लाई विधि को परिभाषित करता है। इसका मतलब यह है कि हर बार जिसे इसे कहा जाता है, एक "विधि वस्तु" बनाई जाएगी। विधियों के लिए प्रोटोटाइप का उपयोग करने के लिए बेहतर! यदि आप चाहें तो आप इसे कन्स्ट्रक्टर में रख सकते हैं - आपको केवल गार्ड की आवश्यकता है ताकि आप वास्तव में प्रोटोटाइप को एक बार (छद्म) शुरू कर सकें: यदि (SuperCar.prototype.myMethod! = 'Function') ... तो परिभाषित करें आपका प्रोटोटाइप शाब्दिक।
  5. 'कार.call (यह, नाम) क्यों कॉल करें ....': मेरे पास आपके कोड पर सावधानी से देखने का समय नहीं है, इसलिए मैं गलत हो सकता हूं लेकिन आमतौर पर ऐसा होता है कि प्रत्येक उदाहरण इसे स्वयं का राज्य रख सकता है ऊपर वर्णित प्रोटोटाइप चेनिंग के 'staticy' व्यवहार मुद्दे को ठीक करने के लिए।

अन्त में, मुझे लगता है मैं TDD जावास्क्रिप्ट विरासत कोड के कई उदाहरण है कि यहां काम करता है कि उल्लेख करना चाहते हैं: TDD JavaScript Inheritance Code and Essay मैं आपकी प्रतिक्रिया के रूप में मैं इसे बेहतर बनाने और रखने के लिए आशा करती हूं कि प्राप्त करके प्रसन्नता होगी यह खुला स्रोत । लक्ष्य शास्त्रीय प्रोग्रामर को जावास्क्रिप्ट के साथ तेजी से बढ़ने में मदद करना है और क्रॉकफोर्ड और जाकास दोनों पुस्तकों के अध्ययन को भी पूरक बनाना है।

+1

मैं अब बिंदु (1) से पहले आया हूं। मैंने पाया कि यदि नए कीवर्ड का उपयोग नहीं किया गया है और बस Superclass.call (यह) (तो SuperCar = {Car.call (यह);}; SuperCar.prototype = कार;) का उपयोग किया गया था, यह काम करने लग रहा था। क्या ऐसा करने का कोई कारण नहीं है? (नेक्रो के लिए माफ़ी) – obie

+0

* क्लासिक * ओओपी भाषाओं से आ रहा है, मुझे हमेशा * अजीब * प्रोटोटाइप श्रृंखला – superjos

+0

अच्छी किताब भरने के लिए * नया * उदाहरण * बस * बनाने की आवश्यकता है। आपको ध्यान रखना चाहिए कि जिथब पेज के शीर्ष पर स्थित लिंक टूटा हुआ है, बेशक, यह सामग्री में पाया जा सकता है। –

0
function abc() { 
} 

प्रोटोटाइप तरीकों और संपत्ति समारोह एबीसी के लिए बनाई गई

abc.prototype.testProperty = 'Hi, I am prototype property'; 
abc.prototype.testMethod = function() { 
    alert('Hi i am prototype method') 
} 

समारोह एबीसी के लिए नए उदाहरणों बनाना

var objx = new abc(); 

console.log(objx.testProperty); // will display Hi, I am prototype property 
objx.testMethod();// alert Hi i am prototype method 

var objy = new abc(); 

console.log(objy.testProperty); //will display Hi, I am prototype property 
objy.testProperty = Hi, I am over-ridden prototype property 

console.log(objy.testProperty); //will display Hi, I am over-ridden prototype property 

http://astutejs.blogspot.in/2015/10/javascript-prototype-is-easy.html

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