2012-07-02 14 views
9

वस्तुओं का एक वर्ग के लिए गुणों और विधियों की घोषणा करने के लिए एक प्रोटोटाइप का उपयोग किया जाता है। प्रोटोटाइप का उपयोग करने का एक फायदा यह है कि यह स्मृति को संरक्षित करता है क्योंकि कक्षा के सभी उदाहरण प्रोटोटाइप के गुणों और विधियों को इंगित करते हैं जो स्मृति को संरक्षित करते हैं और प्रभावी रूप से गुणों को वर्ग के सभी उदाहरणों से स्थैतिक माना जाता है।क्या ऑब्जेक्ट पर संपत्ति घोषित करने के बजाए प्रोटोटाइप का उपयोग करने का कोई फायदा है?

प्रोटोटाइप का उपयोग प्रोटोटाइप चेनिंग के माध्यम से विरासत के लिए किया जाता है।

मेरा प्रश्न बहुत आसान है। प्रोटोटाइप का उपयोग क्यों करें जब आप बस कर सकते हैं:

function car() { 
    this.engine = "v8"; 
} 
function mustang() { 
    // nm, no good way to inherit without using prototypes 
} 

क्या यह सही है? तो प्रोटोटाइप का प्राथमिक उद्देश्य तिगुना है:

  1. संरक्षण स्मृति
  2. स्थिर गुण प्रदान
  3. एक संदर्भ प्रकार एक सुपर वर्ग
+1

मुझे यकीन नहीं है कि आप क्या पूछ रहे हैं ... आपको लगता है कि "आप बस कर सकते हैं ...", लेकिन फिर उस स्क्रिप्ट में टिप्पणी में आप कहते हैं "इसे करने का कोई अच्छा तरीका नहीं है" । क्या वह खुद का विरोधाभास नहीं करता है? – Joeytje50

+1

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

+0

यदि आप प्रोटोटाइप का उपयोग नहीं करते हैं तो आप फ़ंक्शन mustang() {car.apply (यह) कर सकते हैं; } – Serge

उत्तर

0

प्रोटोटाइप से इनहेरिट करना के लिए एक ही रास्ता है एक बहुत है उस से भी अधिक। आप रनटाइम के दौरान विधियों और गुणों के साथ कक्षाओं और वस्तुओं के पहले से मौजूद मौजूदा उदाहरण भी बढ़ा सकते हैं। ताकि लोगों को (और आप सड़क के नीचे) वास्तव में अपने कोड को समझते हैं, आप नहीं this.engine="v8" निर्माता में क्या रखना चाहिए http://javascript.info/tutorial/inheritance

0

आप सम्मेलनों निम्नलिखित पर ध्यान देते हैं:

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

1

के संबंध में अपने तीन अंक:

  1. प्रोटोटाइप जरूरी अधिक performant, विशेष रूप से प्रोटोटाइप जंजीरों कि लंबे समय से बन या कई सदस्यों को शामिल करने के लिए नहीं हैं। प्रोटोटाइप जितना छोटा होगा और चेन को छोटा करेगा, उतना ही ब्राउज़र का कंपाइलर इसे अनुकूलित कर सकता है। आखिरकार, इस सवाल को व्यक्तिगत अनुप्रयोगों, उनकी व्यक्तिगत जरूरतों और लक्षित ब्राउज़र के लिए पूछा जाना चाहिए (जो प्रदर्शन में व्यापक रूप से भिन्न हो सकते हैं)।
  2. परिभाषा के अनुसार, स्थिर सदस्यों को वस्तुओं की आवश्यकता होती है। यही है, स्थिर सदस्य एक विशिष्ट उदाहरण के बजाय एक वस्तु से संबंधित हैं। ऑब्जेक्ट्स जावास्क्रिप्ट में स्थैतिक गुण बनाने का एकमात्र तरीका है। ध्यान दें कि ऑब्जेक्ट अक्षर, जो "विशेष" प्रकार के ऑब्जेक्ट हैं, अनिवार्य रूप से स्थैतिक हैं।
  3. कोई अपनी खुद की वस्तु को कार्यान्वित कर सकता है जो विरासत (यानी, jQuery.extend) जैसे कुछ के लिए अनुमति देगा, लेकिन जहां तक ​​संदर्भ प्रकार जाते हैं, प्रोटोटाइप विरासत बनाने का एकमात्र तरीका है।
+0

क्या jspref नहीं दिखाता है कि प्रोटोटाइप दूसरों को निष्पादित करता है? केवल क्रोम 2 9 और 30 ही समान हैं। यह प्रति सेकंड संचालन के बारे में है और स्मृति खपत नहीं दिखाता है। बिंदु 3 में; 'कुछ नियोक्ता उदाहरण के लिए व्यक्ति' होने का एकमात्र तरीका प्रोटोटाइप – HMR

+0

एचएमआर का उपयोग करना है, इसे पकड़ने के लिए धन्यवाद - यह मेरे हिस्से पर एक खराब उदाहरण था। मैंने इसके बजाय कारण की व्याख्या करने के लिए उत्तर संपादित किया। –

+0

हां, प्रदर्शन https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain# पर एक नकारात्मक प्रभाव हो सकता है एक लूप में प्रदर्शन जो प्रोटोटाइप श्रृंखला को उच्चतम तरीके से आमंत्रित करता है, आपको नोटिस हो सकता है इस। – HMR

2

संरक्षण स्मृति

हाँ, यह करता है, जब आप कार के उदाहरण के सैकड़ों बना सकते हैं और वे सब अपने स्वयं के कार्य (अपने स्वयं के बंद होने के स्कोप) आप और अधिक स्मृति का उपभोग करेंगे है।

इसके लिए कोई संदर्भ नहीं मिल रहा है लेकिन यह सुझाव दिया गया है कि क्रोम कन्स्ट्रक्टर फ़ंक्शंस को अनुकूलित करता है जो कन्स्ट्रक्टर बॉडी में सबकुछ के साथ कन्स्ट्रक्टर कार्यों से बेहतर प्रोटोटाइप का उपयोग करता है।

स्थिर गुण प्रदान

स्टेटिक, अधिक Date.now() की तरह है हर मामले प्रोटोटाइप से सदस्य हैं लेकिन उदाहरण पर कहा जा सकता है।

एक संदर्भ प्रकार एक सुपर वर्ग

से इनहेरिट करना के लिए आप बच्चे में Parent.apply(this,arguments); साथ वारिस कर सकते हैं एक ही रास्ता है, लेकिन यह विस्तार जनक कार्यों और अधिक जटिल बना देता है और childInstance instanceof Parent सच नहीं है। वह कोड क्या करता है अभिभावक ऑब्जेक्ट (this) के रूप में बाल उदाहरण बनाने के लिए अभिभावक कोड चलाता है। विरासत आमतौर पर 2 स्थानों में किया जाता है।

  1. बाल शरीर Parent.apply(this,arguments); उपयोग जनक initialisation कोड फिर से और जनक उदाहरण सदस्यों बनाने के लिए बाल उदाहरण के सदस्यों (: this.name उदाहरण के लिए) किया जाना है।
  2. Paren.prototype को पेरेंट.प्रोटोटाइप Child.prototype=Object.create(Parent.prototype);Child.prototype.constructor=Child; की उथली प्रतिलिपि पर सेट करना यह सुनिश्चित करेगा कि साझा अभिभावक सदस्य बाल उदाहरणों (जैसे फ़ंक्शन getName) पर उपलब्ध हैं।
ये अंक

अधिक विस्तार यहाँ से वर्णन किया गया: https://stackoverflow.com/a/16063711/1641941

0

अपने अंक के बारे में:

  1. वहाँ विशेष रूप से कार्यों के बारे में, एक प्रदर्शन को बढ़ावा देने निश्चित रूप से है - यह प्रोटोटाइप पर काम करता है की घोषणा करने के लिए बहुत बेहतर है ।
  2. मुझे लगता है कि आपको "सार्वजनिक" गुण कहना है ताकि जानकारी some_instance.foo लिखकर पुनर्प्राप्त की जा सके। "स्टेटिक" गुण/विधियां अलग हैं (नीचे देखें)।
  3. सही। विरासत केवल प्रोटोटाइप से ही हो सकता है।

मुझे कुछ चीजों को समझाने दें कि यह मदद करता है या नहीं। जावास्क्रिप्ट में नई "कक्षाएं" बनाना एक काफी सीधी प्रक्रिया है।

var MyClass = new Function(); 

इस बिंदु पर, इंजन अपने नए वर्ग के बारे में पता है और जानता है कि "क्या करना है" (प्रदर्शन के संदर्भ में) जब वह अपने "वर्ग" के नए उदाहरणों पैदा करता है।

var my_instance = new MyClass(); 

आप प्रोटोटाइप को संशोधित करना चाहते हैं, तो आप ऐसा करते हैं और जानते हैं कि हर उदाहरण अपडेट होने की वजह से वे सभी एक ही प्रोटोटाइप का हिस्सा जा रहा है कर सकते हैं।

MyClass.prototype.name = "default name"; 
console.log(my_instance.name); //=> default name 

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

मैं वास्तव में प्रदर्शन पेशेवरों और एक उदाहरण पर तदर्थ गुण/तरीकों घोषित करने के विपक्ष के लिए बात नहीं कर सकते हैं:

my_instance.foo = function() { /* this is not in the prototype chain */ }; 

मेरा अनुमान है कि इस इंजन के लिए बहुत आसान है और है कोई बड़ा सौदा नहीं जब तक कि आप एक ही समय में हजारों वस्तुओं के लिए ऐसा नहीं कर रहे हैं।

var old_foo = MyClass.prototype.foo; 
MyClass.prototype.foo = function() { 
    /* new business logic here */ 

    // now call the original method. 
    old_foo.apply(this, arguments); 
}; 

के बारे में "स्थिर" गुण:

प्रोटोटाइप IMO उपयोग का मुख्य लाभ यह है कि आप अपने "वर्ग" के सभी उदाहरणों तदनुसार अपडेट कर दिया जाएगा एक विधि की कार्यक्षमता का विस्तार करने और पता करने के लिए कोड लिख सकते हैं , तो आप "वर्ग" पर उन की घोषणा (निर्माता) ही:

// example static property 
MyClass.num_instances = 0; 

अब आप init बना सकते हैं/इस तरह के तरीकों को नष्ट:

MyClass.prototype.init = function() { 
    this.constructor.num_instances++; 
}; 

MyClass.prototype.destroy = function() { 
    this.constructor.num_instances--; 
}; 

// and call the init method any time you create a new instance 
my_instance.init(); 
console.log(MyClass.num_instances); //=> 1 

var instance_2 = new MyClass(); 
instance_2.init(); 
console.log(MyClass.num_instances); //=> 2 

instance_2.destroy(); 
console.log(MyClass.num_instances); //=> 1 

आशा है कि मदद करता है।

0

(1) मुझे नहीं लगता कि अकेले मेमोरी को संरक्षित करना प्रोप्रोटाइप का उपयोग करने का एक वैध कारण है, जब तक आप डुप्लिकेटिंग ऑब्जेक्ट्स के साथ वास्तव में चरम नहीं हो जाते।

(2) स्थैतिक गुणों का विचार वास्तव में उपयोग करने का एक कारण नहीं है। प्रोटीोटाइप या तो (IMHO), क्योंकि यह पारंपरिक स्थिर संपत्ति की तरह व्यवहार नहीं करता है। आप (जहां तक ​​मुझे पता है) हमेशा "स्थिर" संपत्ति तक पहुंचने से पहले ऑब्जेक्ट इंस्टेंस की आवश्यकता होती है, जो इसे स्थिर नहीं बनाता है।

function Car() {} 
Car.prototype.Engine = "V8"; 
// I can't access Car.Engine... I'll always need an instance. 
alert(new Car().Engine); 
// or 
var car1 = new Car(); 
alert(car1.Engine); //you always need an instance. 
//unless you wanted to do 
alert(Car.prototype.Engine); //this is more like a static property, but has an 
//unintended consequence that every instance of Car also receives a .Engine 
//behavior, so don't do this just to create a "static property." 

यह ध्यान देने योग्य है कि इस "स्थिर" विचार न केवल गुण लेकिन सभी सदस्यों, जो विधि (कार्यों) भी शामिल है पर लागू होता है, एक पारंपरिक OO नजरिए से।

प्रोटोटाइप (फिर से, आईएमएचओ) के बारे में सोचना बेहतर है क्योंकि इंजेक्शन वाले सिंगलटन ऑब्जेक्ट्स जो व्यवहार ऑब्जेक्ट्स से जुड़े होते हैं। कार() के सभी उदाहरणों में अपने स्वयं के इंस्टेंस सदस्य हो सकते हैं, लेकिन कार() के हर उदाहरण को सभी कार.प्रोटोटाइप के सदस्यों/व्यवहारों के साथ "स्वचालित रूप से" इंजेक्शन दिया जाएगा। यह तकनीकी रूप से वही नहीं है, लेकिन मुझे इस तरह प्रोटोटाइप के बारे में सोचना सुविधाजनक लगता है।

//define Car and Car.GoFast 
function Car() {} 
Car.prototype.GoFast = function() { alert('vroom!'); }; 

var car1 = new Car(); 
var car2 = new Car(); 

car1.GoFast(); 
car2.GoFast(); //both call to same GoFast implementation on Car.prototype 

//change the GoFast implementation 
Car.prototype.GoFast = function() { alert('vvvvvrrrrroooooooooommmmm!!!!!'); }; 

car1.GoFast(); 
car2.GoFast(); //both have been "updated" with the new implementation because 
//both car1 and car2 are pointing to the same (singleton) Car.prototype object! 

Car.prototype एक सिंगलटन वस्तु जिसके सदस्य/व्यवहार प्रकार कार के कहने वस्तुओं में इंजेक्ट कर दिया है की तरह बर्ताव कर रहा है।

(3) प्रोटोटाइप विरासत के लिए भ्रमित नहीं होना चाहिए। आप व्यवहार प्राप्त कर सकते हैं जो विरासत में प्रतीत होता है, लेकिन ऐसा नहीं है। प्रोटोटाइप पर सदस्य/व्यवहार प्रोटोटाइप ऑब्जेक्ट पर रहते हैं। वे आपकी व्युत्पन्न कक्षा के सदस्य/व्यवहार नहीं बनते हैं, जैसे कि वास्तविक विरासत। यही कारण है कि मैं इसे आपके उदाहरण में "इंजेक्शन" प्रोटोटाइप की तरह वर्णन करता हूं।

function Car() {} 
Car.prototype.Engine = "V8"; 
var car1 = new Car(); 
var car2 = new Car(); 

alert(car1.Engine); //alerts "V8" 
//There is no "Engine" variable defined within the instance scope of 'car1'. 
//Javascript searches the scope of car1's Type.prototype object to find 'Engine'. 
//Equivalent to: Object.getPrototypeOf(car1).Engine 

//But if we create 'Engine' within the scope of car1 
car1.Engine = "V6"; //Car.prototype was never accessed or updated 
alert(car1.Engine); //we get "V6" 
alert(car2.Engine); //we still get "V8" 
alert(Object.getPrototypeOf(car1).Engine); //we still get "V8"! 

तो सीधे सवाल का जवाब देने: वहाँ प्रोटोटाइप का उपयोग कर के बजाय वस्तु पर ही गुण घोषित करने का कोई लाभ है?

हां, जब आप किसी दिए गए प्रकार की ऑब्जेक्ट्स के बीच व्यवहार कार्यान्वयन साझा करना चाहते हैं।एक संयोग के रूप में, आप अपनी स्मृति पदचिह्न को कम कर देंगे, लेकिन प्रोटोटाइप का उपयोग करने के लिए यह अकेला कारण नहीं है। न तो "स्थैतिक गुण बनाना" (जो वे नहीं हैं), या विरासत के लिए (जो यह नहीं है) है।

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

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