सवाल जावास्क्रिप्ट। प्रोटीोटाइप कैसे काम करता है?


मैं गतिशील प्रोग्रामिंग भाषाओं में नहीं हूं, लेकिन मैंने जावास्क्रिप्ट कोड का अपना उचित हिस्सा लिखा है। इस प्रोटोटाइप-आधारित प्रोग्रामिंग के आसपास मुझे कभी भी अपना सिर नहीं मिला, क्या कोई यह जानता है कि यह कैसे काम करता है?

var obj = new Object(); // not a functional object
obj.prototype.test = function() { alert('Hello?'); }; // this is wrong!

function MyObject() {} // a first class functional object
MyObject.prototype.test = function() { alert('OK'); } // OK

मुझे कुछ समय पहले लोगों के साथ बहुत सी चर्चा याद है (मुझे बिल्कुल यकीन नहीं है कि मैं क्या कर रहा हूं) लेकिन जैसा कि मैं इसे समझता हूं, कक्षा की कोई अवधारणा नहीं है। यह सिर्फ एक वस्तु है, और उन वस्तुओं के उदाहरण मूल के क्लोन हैं, है ना?

लेकिन इसका सही उद्देश्य क्या है .prototype जावास्क्रिप्ट में संपत्ति? यह वस्तुओं को तत्काल करने से कैसे संबंधित है?


संपादित करें

इन स्लाइड वास्तव में इस विषय को समझने में बहुत मदद की।


1858
2018-02-21 12:31


मूल


जॉन रेसिग में फंक्शन प्रोटोटाइप पर कुछ स्लाइड्स हैं जो इस विषय को देखते समय मेरे लिए सहायक थीं (आप कोड में बदलाव भी कर सकते हैं और देख सकते हैं कि क्या होता है ...) http://ejohn.org/apps/learn/#64 - John Foster
महान प्रश्न सामग्री, इस प्रश्न को जानकारीपूर्ण रखने के प्रयोजनों के लिए शायद आपकी साइट पर जॉन की साइट से कुछ टिप्पणियां दें, यदि उनकी साइट इस तरह से बदलती है कि आपका लिंक अब उपलब्ध नहीं है। किसी भी तरह से +1, मेरी मदद की। - Chris
अपने लिंक के लिए +1 जॉन रेसिग की जावास्क्रिप्ट निंजा स्लाइड # 64। वहां से शुरू करना वास्तव में सहायक था, और मुझे लगता है कि मैं प्रोटोटाइप को सही ढंग से समझता हूं। - a paid nerd
क्या प्रोटोटाइप लगाने के लिए हमें वास्तव में एक कार्यात्मक वस्तु की आवश्यकता है? अगर हां क्यों? - Anshul
यह आपकी मदद कर सकता है: webdeveasy.com/javascript-prototype - Naor


जवाब:


प्रत्येक जावास्क्रिप्ट ऑब्जेक्ट में एक आंतरिक संपत्ति होती है [[प्रोटोटाइप]]। यदि आप एक संपत्ति के माध्यम से देखते हैं obj.propName या obj['propName'] और ऑब्जेक्ट में ऐसी कोई संपत्ति नहीं है - जिसे चेक किया जा सकता है obj.hasOwnProperty('propName') - रनटाइम इसके बजाय [[प्रोटोटाइप]] संदर्भित ऑब्जेक्ट में संपत्ति को देखता है। यदि प्रोटोटाइप-ऑब्जेक्ट में ऐसी कोई संपत्ति नहीं है, तो इसका प्रोटोटाइप बदले में चेक किया जाता है, इस प्रकार मूल ऑब्जेक्ट को चलाता है प्रोटोटाइप श्रृंखला एक मैच मिलने तक या उसका अंत तक पहुंच जाता है।

कुछ जावास्क्रिप्ट कार्यान्वयन [[प्रोटोटाइप]] संपत्ति तक सीधे पहुंच की अनुमति देते हैं, उदाहरण के लिए नामित गैर-मानक संपत्ति के माध्यम से __proto__। आम तौर पर, वस्तु निर्माण के दौरान ऑब्जेक्ट के प्रोटोटाइप को सेट करना केवल संभव है: यदि आप एक नई वस्तु बनाते हैं new Func(), ऑब्जेक्ट की [[प्रोटोटाइप]] संपत्ति को संदर्भित ऑब्जेक्ट पर सेट किया जाएगा Func.prototype

यह जावास्क्रिप्ट में कक्षाओं को अनुकरण करने की अनुमति देता है, हालांकि जावास्क्रिप्ट की विरासत प्रणाली है - जैसा कि हमने देखा है - प्रोटोटाइपिकल, और क्लास-आधारित नहीं:

बस वर्गों और प्रोटोटाइप के गुणों के रूप में कन्स्ट्रक्टर कार्यों के बारे में सोचें (यानी कन्स्ट्रक्टर फ़ंक्शन के संदर्भ में ऑब्जेक्ट का संदर्भ prototype संपत्ति) साझा सदस्यों के रूप में, यानी सदस्य जो प्रत्येक उदाहरण के लिए समान हैं। कक्षा-आधारित प्रणालियों में, प्रत्येक उदाहरण के लिए विधियों को एक ही तरीके से कार्यान्वित किया जाता है, इसलिए प्रोटोटाइप में सामान्य रूप से विधियों को जोड़ा जाता है, जबकि ऑब्जेक्ट के फ़ील्ड आवृत्ति-विशिष्ट होते हैं और इसलिए निर्माण के दौरान ऑब्जेक्ट में स्वयं को जोड़ा जाता है।


927
2018-02-21 13:33



तो, क्या मैं अपने लघु स्निपेट में प्रोटोटाइप संपत्ति पर नई गुणों को परिभाषित करके कुछ गलत कर रहा हूं? - John Leidegren
मुझे लगता है कि यह पहला वर्ग नागरिकों के रूप में कार्य वस्तुओं का मतलब है। - John Leidegren
मैं गैर मानक चीजों से नफरत करता हूं, खासकर प्रोग्रामिंग भाषाओं में, यहां तक ​​कि एक क्यों है आद्य जब इसकी स्पष्ट रूप से आवश्यकता नहीं है? - John Leidegren
@ एच 1 डी: अगर Class.method नहीं मिला, रनटाइम की तलाश है Class.__proto__.method (या यों कहें Object.getPrototypeOf(Class).method अनुपालन ईएस 5 में) और नहीं  Class.prototype.method - Christoph
ध्यान दें कि इसका उपयोग [[प्रोटोटाइप]] जानबूझकर है - ईसीएमए -262 डबल स्क्वायर ब्रैकेट वाले आंतरिक गुणों के नाम संलग्न करता है - Christoph


जावा, सी # या सी ++ जैसे क्लासिकल विरासत को लागू करने वाली भाषा में आप कक्षा बनाकर शुरू करते हैं - आपकी ऑब्जेक्ट्स के लिए एक ब्लूप्रिंट - और फिर आप उस वर्ग से नई ऑब्जेक्ट्स बना सकते हैं या आप कक्षा का विस्तार कर सकते हैं, जो कि एक नई कक्षा को परिभाषित करता है मूल वर्ग

जावास्क्रिप्ट में आप पहले एक ऑब्जेक्ट बनाते हैं (कक्षा की कोई अवधारणा नहीं है), तो आप अपनी ऑब्जेक्ट बढ़ा सकते हैं या इससे नई ऑब्जेक्ट्स बना सकते हैं। यह मुश्किल नहीं है, लेकिन शास्त्रीय तरीके से इस्तेमाल किसी के लिए चयापचय करने के लिए थोड़ा विदेशी और कठिन है।

उदाहरण:

//Define a functional object to hold persons in JavaScript
var Person = function(name) {
  this.name = name;
};

//Add dynamically to the already defined object a new getter
Person.prototype.getName = function() {
  return this.name;
};

//Create a new object of type Person
var john = new Person("John");

//Try the getter
alert(john.getName());

//If now I modify person, also John gets the updates
Person.prototype.sayMyName = function() {
  alert('Hello, my name is ' + this.getName());
};

//Call the new method on john
john.sayMyName();

अब तक मैं मूल वस्तु का विस्तार कर रहा हूं, अब मैं एक और वस्तु बना रहा हूं और फिर व्यक्ति से विरासत में हूं।

//Create a new object of type Customer by defining its constructor. It's not 
//related to Person for now.
var Customer = function(name) {
    this.name = name;
};

//Now I link the objects and to do so, we link the prototype of Customer to 
//a new instance of Person. The prototype is the base that will be used to 
//construct all new instances and also, will modify dynamically all already 
//constructed objects because in JavaScript objects retain a pointer to the 
//prototype
Customer.prototype = new Person();     

//Now I can call the methods of Person on the Customer, let's try, first 
//I need to create a Customer.
var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();

//If I add new methods to Person, they will be added to Customer, but if I
//add new methods to Customer they won't be added to Person. Example:
Customer.prototype.setAmountDue = function(amountDue) {
    this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function() {
    return this.amountDue;
};

//Let's try:       
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());

var Person = function (name) {
    this.name = name;
};
Person.prototype.getName = function () {
    return this.name;
};
var john = new Person("John");
alert(john.getName());
Person.prototype.sayMyName = function () {
    alert('Hello, my name is ' + this.getName());
};
john.sayMyName();
var Customer = function (name) {
    this.name = name;
};
Customer.prototype = new Person();

var myCustomer = new Customer('Dream Inc.');
myCustomer.sayMyName();
Customer.prototype.setAmountDue = function (amountDue) {
    this.amountDue = amountDue;
};
Customer.prototype.getAmountDue = function () {
    return this.amountDue;
};
myCustomer.setAmountDue(2000);
alert(myCustomer.getAmountDue());

जैसा कि कहा गया है कि मैं setAmountDue (), किसी व्यक्ति पर getAmountDue () को कॉल नहीं कर सकता।

//The following statement generates an error.
john.setAmountDue(1000);

1755
2018-01-24 03:42



मुझे लगता है कि स्टैक ओवरफ्लो पर उत्तर न केवल मूल पोस्टर के लिए दिलचस्प हैं, बल्कि खोजों से छिपकर या आने वाले अन्य लोगों के एक बड़े समुदाय के लिए भी दिलचस्प हैं। और मैं उनमें से एक रहा हूं और मुझे पुरानी पोस्ट से फायदा हुआ था। मुझे लगता है कि मैं कुछ कोड उदाहरणों को जोड़ने के अन्य उत्तरों में योगदान दे सकता हूं। आपके प्रश्न के बारे में: यदि आप नया छोड़ देते हैं, तो यह काम नहीं करता है। जब मैं myCustomer.sayMyName () को कॉल करता हूं तो यह "myCustomer.sayMyName एक फ़ंक्शन नहीं है" देता है। सबसे आसान तरीका फायरबग के साथ प्रयोग है और देखें कि क्या होता है। - stivlo
जहां तक ​​मैं विभिन्न व्यक्ति = कार्य (नाम) {...} समझता हूं; व्यक्ति ऑब्जेक्ट्स बनाने में सक्षम एक कन्स्ट्रक्टर फ़ंक्शन को परिभाषित कर रहा है। तो अभी तक कोई ऑब्जेक्ट नहीं है, केवल अज्ञात कन्स्ट्रक्टर फ़ंक्शन व्यक्ति को सौंपा गया है। यह एक बहुत अच्छी व्याख्या है: helephant.com/2008/08/how-javascript-objects-work - stivlo
चेतावनी: यह उत्तर इस तथ्य को उपेक्षा करता है कि पेरेंट क्लास कन्स्ट्रक्टर को प्रति उदाहरण आधार पर नहीं कहा जाता है। यह काम करने का एकमात्र कारण यह है कि उसने बच्चे और अभिभावक दोनों कन्स्ट्रक्टर में एक ही चीज़ (नाम सेट करना) किया था। जावास्क्रिप्ट (और अंतिम समाधान) में विरासत का प्रयास करते समय सामान्य गलतियों पर गहराई से स्पष्टीकरण के लिए, कृपया देखें: यह ढेर ओवरफ्लो पोस्ट - Aaren Cordova
मैंने देखा कि इस उत्तर में यह भी उल्लेख नहीं किया गया है कि प्रोटोटाइप के रूप में "नया व्यक्ति ()" का उपयोग करके, आप वास्तव में "व्यक्ति" की "संपत्ति" संपत्ति संपत्ति को "ग्राहक" की स्थिर संपत्ति होने के लिए सेट कर रहे हैं (इसलिए सभी ग्राहक उदाहरणों में एक ही संपत्ति होगी)। हालांकि यह एक अच्छा मूल उदाहरण है, ऐसा मत करो। :) "Person.prototype" पर प्रोटोटाइप सेट करके "पुल" के रूप में कार्य करने के लिए एक नया अनाम फ़ंक्शन बनाएं, फिर इसके द्वारा एक उदाहरण बनाएं और इसके बजाय उस अज्ञात उदाहरण पर "customer.prototype" सेट करें। - James Wilkins
बारे में Customer.prototype = new Person(); लाइन, एमडीएन का उपयोग कर एक उदाहरण दिखाता है Customer.prototype = Object.create(Person.prototype), और कहा कि 'यहां एक आम त्रुटि है "नया व्यक्ति ()"'। स्रोत - Rafael Eyng


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


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

function Person(name){
    this.name = name;
}
Person.prototype.getName = function(){
    console.log(this.name);
}
var person = new Person("George");

प्रोटोटाइप अवधारणा के माध्यम से जाने से पहले हमें कुछ महत्वपूर्ण बिंदुओं पर विचार करना होगा।

1- जावास्क्रिप्ट फ़ंक्शन वास्तव में कैसे काम करते हैं:

पहला कदम उठाने के लिए हमें यह पता लगाना होगा कि जावास्क्रिप्ट फ़ंक्शंस वास्तव में कैसे कार्य करता है, जैसे कि फ़ंक्शन का उपयोग करने वाली कक्षा this इसमें कीवर्ड या इसके तर्कों के साथ नियमित कार्य के रूप में, यह क्या करता है और यह क्या लौटाता है।

मान लें कि हम एक बनाना चाहते हैं Person ऑब्जेक्ट मॉडल लेकिन इस चरण में मैं कोशिश कर रहा हूँ उपयोग किए बिना वही सटीक चीज करें prototype तथा new कीवर्ड

तो इस चरण में functions, objects तथा this कीवर्ड, हमारे पास सब कुछ है।

पहला सवाल होगा किस तरह this कीवर्ड उपयोग किए बिना उपयोगी हो सकता है new कीवर्ड

तो जवाब देने के लिए कि मान लें कि हमारे पास एक खाली वस्तु है, और दो कार्य जैसे:

var person = {};
function Person(name){  this.name = name;  }

function getName(){
    console.log(this.name);
}

और अब बिना उपयोग किए new कीवर्ड हम इन कार्यों का उपयोग कैसे कर सकते हैं। तो जावास्क्रिप्ट को ऐसा करने के 3 अलग-अलग तरीके हैं:

ए। पहला तरीका केवल फ़ंक्शन को नियमित फ़ंक्शन के रूप में कॉल करना है:

Person("George");
getName();//would print the "George" in the console

इस मामले में, यह वर्तमान संदर्भ वस्तु होगी, जो आमतौर पर वैश्विक है window ब्राउज़र में ऑब्जेक्ट या GLOBAL में Node.js। इसका मतलब है कि हमारे पास ब्राउज़र में window.name होगा, Node.js में GLOBAL.name, "जॉर्ज" के मूल्य के साथ।

ख। हम कर सकते हैं संलग्न करें उन्हें एक वस्तु के रूप में, इसकी संपत्ति के रूप में

-सबसे आसान तरीका ऐसा करने के लिए खाली संशोधन कर रहा है person वस्तु, जैसे:

person.Person = Person;
person.getName = getName;

इस तरह हम उन्हें कॉल कर सकते हैं:

person.Person("George");
person.getName();// -->"George"

और अब person वस्तु इस तरह है:

Object {Person: function, getName: function, name: "George"}

-एक संपत्ति संलग्न करने का दूसरा तरीका एक वस्तु के लिए उपयोग कर रहा है prototype उस वस्तु का जो किसी भी जावास्क्रिप्ट ऑब्जेक्ट में नाम के साथ मिल सकता है __proto__, और मैंने सारांश भाग पर थोड़ा सा व्याख्या करने की कोशिश की है। तो हम ऐसा करके समान परिणाम प्राप्त कर सकते हैं:

person.__proto__.Person = Person;
person.__proto__.getName = getName;

परंतु इस तरह हम वास्तव में क्या कर रहे हैं संशोधित कर रहा है Object.prototype, क्योंकि जब भी हम अक्षर का उपयोग कर जावास्क्रिप्ट ऑब्जेक्ट बनाते हैं ({ ... }), यह आधारित के आधार पर बनाया जाता है Object.prototype, जिसका अर्थ यह है कि यह नव निर्मित वस्तु से जुड़ी एक विशेषता के रूप में जुड़ा हुआ है __proto__ , इसलिए यदि हम इसे बदलते हैं, जैसा कि हमने अपने पिछले कोड स्निपेट पर किया है, तो सभी जावास्क्रिप्ट ऑब्जेक्ट्स बदल जाएंगे, अच्छे अभ्यास नहीं। तो अब बेहतर अभ्यास क्या हो सकता है:

person.__proto__ = {
    Person: Person,
    getName: getName
};

और अब अन्य वस्तुएं शांति में हैं, लेकिन यह अभी भी एक अच्छा अभ्यास प्रतीत नहीं होता है। तो हमारे पास अभी भी एक और समाधान है, लेकिन इस समाधान का उपयोग करने के लिए हमें कोड की उस पंक्ति पर वापस जाना चाहिए person ऑब्जेक्ट बनाया गया (var person = {};) फिर इसे इस तरह बदलें:

var propertiesObject = {
    Person: Person,
    getName: getName
};
var person = Object.create(propertiesObject);

यह एक नई जावास्क्रिप्ट बना रहा है Object और संलग्न करें propertiesObject को __proto__ विशेषता। तो यह सुनिश्चित करने के लिए कि आप कर सकते हैं:

console.log(person.__proto__===propertiesObject); //true

लेकिन यहां मुश्किल बात यह है कि आपके पास परिभाषित सभी गुणों तक पहुंच है __proto__ के पहले स्तर पर person वस्तु (अधिक विस्तार के लिए सारांश भाग पढ़ें)।


जैसा कि आप इन दो तरीकों में से किसी एक का उपयोग करते हुए देखते हैं this बिल्कुल इंगित करेंगे person वस्तु।

सी। जावास्क्रिप्ट के साथ समारोह प्रदान करने का एक और तरीका है this, जो उपयोग कर रहा है कॉल या लागू करें समारोह का आह्वान करने के लिए।

लागू () विधि किसी दिए गए मान के साथ फ़ंक्शन को कॉल करती है और   एक सरणी (या एक सरणी जैसी वस्तु) के रूप में प्रदान किए गए तर्क।

तथा

कॉल () विधि किसी दिए गए मान के साथ फ़ंक्शन को कॉल करती है और   तर्क अलग-अलग प्रदान किए जाते हैं।

इस तरह से मेरा पसंदीदा है, हम आसानी से हमारे कार्यों को कॉल कर सकते हैं जैसे:

Person.call(person, "George");

या

//apply is more useful when params count is not fixed
Person.apply(person, ["George"]);

getName.call(person);   
getName.apply(person);

प्रोप्रोटाइप कार्यक्षमता को समझने के लिए ये 3 विधियां महत्वपूर्ण प्रारंभिक चरण हैं।


2- कैसे करता है new कीवर्ड काम करता है?

यह समझने का दूसरा कदम है .prototype कार्यक्षमता। यही वह प्रक्रिया है जो मैं प्रक्रिया को अनुकरण करने के लिए उपयोग करता हूं:

function Person(name){  this.name = name;  }
my_person_prototype = { getName: function(){ console.log(this.name); } };

इस भाग में मैं जावास्क्रिप्ट को ले जाने वाले सभी चरणों को लेने के बिना कोशिश कर रहा हूं new कीवर्ड और prototype, जब आप उपयोग करते हैं new कीवर्ड। तो जब हम करते हैं new Person("George"), Person फ़ंक्शन एक कन्स्ट्रक्टर के रूप में कार्य करता है, ये जावास्क्रिप्ट करता है, एक-एक करके:

ए। सबसे पहले यह एक खाली वस्तु बनाता है, मूल रूप से एक खाली हैश की तरह:

var newObject = {};

ख। जावास्क्रिप्ट लेता है कि अगला कदम है संलग्न करें नव निर्मित वस्तु के लिए सभी प्रोटोटाइप ऑब्जेक्ट्स

हमारे पास है my_person_prototype प्रोटोटाइप ऑब्जेक्ट के समान यहाँ।

for(var key in my_person_prototype){
    newObject[key] = my_person_prototype[key];
}

ऐसा नहीं है कि जावास्क्रिप्ट वास्तव में प्रोटोटाइप में परिभाषित गुणों को जोड़ता है। वास्तविक तरीका प्रोटोटाइप श्रृंखला अवधारणा से संबंधित है।


ए। और बी। इन दो चरणों के बजाय आप एक ही परिणाम कर सकते हैं:

var newObject = Object.create(my_person_prototype);
//here you can check out the __proto__ attribute
console.log(newObject.__proto__ === my_person_prototype); //true
//and also check if you have access to your desired properties
console.log(typeof newObject.getName);//"function"

अब हम कॉल कर सकते हैं getName हमारे में काम करो my_person_prototype:

newObject.getName();

सी। तो यह उस वस्तु को कन्स्ट्रक्टर को देता है,

हम इसे अपने नमूने के साथ कर सकते हैं जैसे:

Person.call(newObject, "George");

या

Person.apply(newObject, ["George"]);

तो कन्स्ट्रक्टर जो कुछ भी चाहता है वह कर सकता है, क्योंकि इस उस कन्स्ट्रक्टर के अंदर वह वस्तु है जो अभी बनाई गई थी।

अब अन्य चरणों को अनुकरण करने से पहले अंतिम परिणाम:     ऑब्जेक्ट {नाम: "जॉर्ज"}


सारांश:

असल में, जब आप इसका उपयोग करते हैं नया फ़ंक्शन पर कीवर्ड, आप उस पर कॉल कर रहे हैं और वह फ़ंक्शन एक कन्स्ट्रक्टर के रूप में कार्य करता है, इसलिए जब आप कहते हैं:

new FunctionName()

जावास्क्रिप्ट आंतरिक रूप से एक ऑब्जेक्ट बनाता है, एक खाली हैश और फिर यह उस ऑब्जेक्ट को कन्स्ट्रक्टर को देता है, फिर कन्स्ट्रक्टर जो चाहें वह कर सकता है, क्योंकि इस उस कन्स्ट्रक्टर के अंदर वह ऑब्जेक्ट है जो अभी बनाया गया था और फिर यह आपको उस ऑब्जेक्ट को देता है यदि आपने अपने फ़ंक्शन में रिटर्न स्टेटमेंट का उपयोग नहीं किया है या आपने इसे रखा है return undefined; अपने समारोह शरीर के अंत में।

तो जब जावास्क्रिप्ट किसी ऑब्जेक्ट पर किसी प्रॉपर्टी को देखने के लिए जाता है, तो यह पहली चीज करता है, क्या यह उस ऑब्जेक्ट पर दिखता है। और फिर एक गुप्त संपत्ति है [[prototype]] जिसे हम आमतौर पर पसंद करते हैं __proto__ और वह संपत्ति है जो जावास्क्रिप्ट को आगे देखती है। और जब यह देखता है __proto__, जहां तक ​​यह एक और जावास्क्रिप्ट ऑब्जेक्ट है, इसका अपना स्वयं का है __proto__विशेषता, यह तब तक ऊपर और ऊपर जाता है जब तक यह उस बिंदु तक नहीं पहुंच जाता है जहां अगला __proto__ शून्य है। बिंदु जावास्क्रिप्ट में एकमात्र वस्तु है कि इसकी __proto__ विशेषता शून्य है Object.prototype वस्तु:

console.log(Object.prototype.__proto__===null);//true

और इस तरह जावास्क्रिप्ट जावास्क्रिप्ट में काम करता है।

The prototype chain

दूसरे शब्दों में, जब आपके पास किसी फ़ंक्शन पर प्रोटोटाइप प्रॉपर्टी होती है और आप उस पर एक नया कॉल करते हैं, जावास्क्रिप्ट समाप्त होने के बाद गुणों के लिए उस नव निर्मित ऑब्जेक्ट को देखता है, तो यह फ़ंक्शन के बारे में देखेगा .prototype और यह भी संभव है कि इस ऑब्जेक्ट का अपना आंतरिक प्रोटोटाइप हो। और इसी तरह।


163
2018-02-13 19:32



ए) कृपया गुणों की प्रतिलिपि बनाकर प्रोटोटाइप की व्याख्या न करें b) आंतरिक सेट करना [[प्रोटोटाइप]] उदाहरण पर कन्स्ट्रक्टर फ़ंक्शन लागू होने से पहले होता है, कृपया उस ऑर्डर को बदलें c) jQuery इस प्रश्न में पूरी तरह से ऑफटॉप है - Bergi
@ बर्गि: इंगित करने के लिए धन्यवाद, अगर आप मुझे ठीक बताते हैं तो मुझे सराहना की जाएगी। - Mehran Hatami
क्या आप इसे सरल बना सकते हैं? आप सभी बिंदुओं पर सही हैं, लेकिन जो छात्र इस स्पष्टीकरण को पढ़ते हैं वे पहली बार वास्तव में भ्रमित हो सकते हैं। किसी भी सरल उदाहरण को उठाएं, और कोड को स्वयं को समझाएं या स्पष्ट करने के लिए टिप्पणियों का एक समूह जोड़ें। - P.M
@ पीएम: आपकी प्रतिक्रिया के लिए धन्यवाद। मैंने इसे यथासंभव सरल बनाने की कोशिश की है, लेकिन मुझे लगता है कि आप सही हैं, अभी भी कुछ अस्पष्ट बिंदु हैं। तो मैं इसे संशोधित करने और अधिक वर्णनात्मक होने की कोशिश करूंगा। :) - Mehran Hatami
अपनी "पुस्तक" के अंत में चित्रण के लिए +1 :) - sargas


prototype आपको कक्षाएं बनाने की अनुमति देता है। यदि आप उपयोग नहीं करते हैं prototype तो यह एक स्थिर हो जाता है।

यहां एक छोटा उदाहरण है।

var obj = new Object();
obj.test = function() { alert('Hello?'); };

उपरोक्त मामले में, आपके पास स्थिर funcation कॉल परीक्षण है। इस फ़ंक्शन को केवल obj.test द्वारा एक्सेस किया जा सकता है जहां आप ओबीजे को कक्षा बनने की कल्पना कर सकते हैं।

जहां नीचे दिए गए कोड में है

function obj()
{
}

obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();

ओबीजी एक वर्ग बन गया है जिसे अब तत्काल किया जा सकता है। ओबीजे के कई उदाहरण मौजूद हो सकते हैं और उनके पास सभी हैं test समारोह।

उपरोक्त मेरी समझ है। मैं इसे एक समुदाय विकी बना रहा हूं, इसलिए यदि मैं गलत हूं तो लोग मुझे सही कर सकते हैं।


66
2017-11-07 09:48



-1: prototype रचनाकार कार्यों की एक संपत्ति है, उदाहरण नहीं, यानी आपका कोड गलत है! शायद आप गैर मानक संपत्ति का मतलब था __proto__ वस्तुओं का, लेकिन यह एक पूरी तरह से अलग जानवर है ... - Christoph
@ क्रिस्टोफ - इसे इंगित करने के लिए धन्यवाद। मैंने नमूना कोड अपडेट किया है। - Ramesh
यह एक अच्छा जवाब है, लेकिन इसके लिए और भी कुछ है। - John Leidegren
इसके लिए बहुत कुछ है ... प्लस जावास्क्रिप्ट एक वर्ग-आधारित भाषा नहीं है - यह प्रोटोटाइप के माध्यम से विरासत से संबंधित है, आपको अंतरों को अधिक विस्तार से कवर करने की आवश्यकता है! - James
मुझे लगता है कि यह जवाब थोड़ा गुमराह है। - Armin Cifuentes


इस धागे को पढ़ने के बाद, मुझे जावास्क्रिप्ट प्रोटोटाइप चेन से उलझन में लग रहा है, तो मुझे इन चार्टों को मिला

http://iwiki.readthedocs.org/en/latest/javascript/js_core.html#inheritance *[[protytype]]* and <code>prototype</code> property of function objects

प्रोटोटाइप चेन द्वारा जावास्क्रिप्ट विरासत दिखाने के लिए यह एक स्पष्ट चार्ट है

तथा

http://www.javascriptbank.com/javascript/article/JavaScript_Classical_Inheritance/

इस में कोड और कई अच्छे आरेखों के साथ एक उदाहरण है।

प्रोटोटाइप श्रृंखला अंततः ऑब्जेक्ट.प्रोटोटाइप पर वापस आती है।

प्रोटोटाइप श्रृंखला को तकनीकी रूप से तब तक बढ़ाया जा सकता है जब तक आप चाहते हैं, प्रत्येक बार अभिभावक वर्ग के किसी ऑब्जेक्ट के बराबर उप-वर्ग के प्रोटोटाइप को सेट करके।

उम्मीद है कि जावास्क्रिप्ट प्रोटोटाइप चेन को समझना आपके लिए भी उपयोगी है।


59
2018-05-26 20:40



यह बहुत अच्छा होगा अगर आप लिंक की सामग्री का संक्षिप्त सार प्रदान कर सकें, इसलिए जब लिंक मर जाएंगे तो यह उत्तर अभी भी उपयोगी होगा। - Nicktar
@ निकटर, आपके सुझाव के लिए धन्यवाद, मैंने इन लिंक द्वारा सरल विवरण जोड़ा है। - rockXrock
एक स्पष्ट चार्ट है? :) - Nuno_147
एक आरेख एक हजार शब्द बोलता है। यह बहुत उपयोगी है :) - Mark Robson
क्या आप समझा सकते हैं [[Prototype]] माध्यम? - CodyBugstein


प्रोटोटाइप के सात Koans

गहरी ध्यान के बाद सर्ओ सैन माउंट फायर फॉक्स से निकल गया, उसका दिमाग स्पष्ट और शांतिपूर्ण था।

हालांकि उसका हाथ बेचैन था, और खुद ही एक ब्रश पकड़ लिया और निम्नलिखित नोट्स नीचे झटका लगा।


0) दो अलग-अलग चीजों को "प्रोटोटाइप" कहा जा सकता है:

  • प्रोटोटाइप संपत्ति, के रूप में obj.prototype

  • प्रोटोटाइप आंतरिक संपत्ति, के रूप में दर्शाया गया है [[Prototype]]  ईएस 5 में

    इसे ES5 के माध्यम से पुनर्प्राप्त किया जा सकता है Object.getPrototypeOf()

    फ़ायरफ़ॉक्स इसे के माध्यम से सुलभ बनाता है __proto__ एक विस्तार के रूप में संपत्ति। ES6 अब उल्लेख करता है के लिए कुछ वैकल्पिक आवश्यकताओं __proto__


1) प्रश्नों का उत्तर देने के लिए ये अवधारणाएं मौजूद हैं:

जब मैं करता हूं obj.property, जेएस कहां देखता है .property?

सहजता से, शास्त्रीय विरासत संपत्ति लुकअप को प्रभावित करना चाहिए।


2)

  • __proto__ डॉट के लिए प्रयोग किया जाता है . के रूप में संपत्ति लुकअप obj.property
  • .prototype है नहीं लुकअप के लिए इस्तेमाल किया जाता है, केवल अप्रत्यक्ष रूप से यह निर्धारित करता है __proto__ ऑब्जेक्ट सृजन पर new

लुकअप ऑर्डर है:

  • obj गुणों के साथ जोड़ा गया obj.p = ... या Object.defineProperty(obj, ...)
  • के गुण obj.__proto__
  • के गुण obj.__proto__.__proto__, और इसी तरह
  • अगर कुछ __proto__ है null, वापसी undefined

यह तथाकथित है प्रोटोटाइप श्रृंखला

आप से बच सकते हैं . के साथ देखो obj.hasOwnProperty('key') तथा Object.getOwnPropertyNames(f)


3) सेट करने के दो मुख्य तरीके हैं obj.__proto__:

  • new:

    var F = function() {}
    var f = new F()
    

    फिर new का गठन किया गया है:

    f.__proto__ === F.prototype
    

    इस कहाँ है .prototype इस्तेमाल हो जाता है।

  • Object.create:

     f = Object.create(proto)
    

    सेट:

    f.__proto__ === proto
    

4) कोड:

var F = function() {}
var f = new F()

निम्नलिखित आरेख के अनुरूप है:

(Function)       (  F  )                                      (f)
 |  ^             | | ^                                        |
 |  |             | | |                                        |
 |  |             | | +-------------------------+              |
 |  |constructor  | |                           |              |
 |  |             | +--------------+            |              |
 |  |             |                |            |              |
 |  |             |                |            |              |
 |[[Prototype]]   |[[Prototype]]   |prototype   |constructor   |[[Prototype]]
 |  |             |                |            |              |
 |  |             |                |            |              |
 |  |             |                | +----------+              |
 |  |             |                | |                         |
 |  |             |                | | +-----------------------+
 |  |             |                | | |
 v  |             v                v | v
(Function.prototype)              (F.prototype)
 |                                 |
 |                                 |
 |[[Prototype]]                    |[[Prototype]]
 |                                 |
 |                                 |
 | +-------------------------------+
 | |
 v v
(Object.prototype)
 | | ^
 | | |
 | | +---------------------------+
 | |                             |
 | +--------------+              |
 |                |              |
 |                |              |
 |[[Prototype]]   |constructor   |prototype
 |                |              |
 |                |              |
 |                | -------------+
 |                | |
 v                v |
(null)           (Object)

यह चित्र कई भाषा पूर्वनिर्धारित ऑब्जेक्ट नोड्स दिखाता है: null, Object, Object.prototype, Function तथा Function.prototype। कोड की हमारी 2 लाइनें केवल बनाई गई हैं f, F तथा F.prototype


5)  .constructor आम तौर पर से आता है F.prototype के माध्यम से . देखो:

f.constructor === F
!f.hasOwnProperty('constructor')
Object.getPrototypeOf(f) === F.prototype
F.prototype.hasOwnProperty('constructor')
F.prototype.constructor === f.constructor

जब हम लिखते हैं f.constructorजावास्क्रिप्ट करता है . के रूप में देखो:

  • f नहीं है .constructor
  • f.__proto__ === F.prototype है .constructor === F, इसलिए इसे ले लें

परिणाम f.constructor == F तब से सहजता से सही है F निर्माण के लिए प्रयोग किया जाता है f, उदा। क्लासिक ओओपी भाषाओं की तरह फ़ील्ड सेट करें।


6) प्रोटोटाइप श्रृंखलाओं में हेरफेर करके क्लासिकल विरासत वाक्यविन्यास प्राप्त किया जा सकता है।

ES6 जोड़ता है class तथा extends कीवर्ड, जो पहले संभव प्रोटोटाइप हेरफेर पागलपन के लिए सिंटैक्स चीनी हैं।

class C {
    constructor(i) {
        this.i = i
    }
    inc() {
        return this.i + 1
    }
}

class D extends C {
    constructor(i) {
        super(i)
    }
    inc2() {
        return this.i + 2
    }
}
// Inheritance syntax works as expected.
(new C(1)).inc() === 2
(new D(1)).inc() === 2
(new D(1)).inc2() === 3
// "Classes" are just function objects.
C.constructor === Function
C.__proto__ === Function.prototype
D.constructor === Function
// D is a function "indirectly" through the chain.
D.__proto__ === C
D.__proto__.__proto__ === Function.prototype
// "extends" sets up the prototype chain so that base class
// lookups will work as expected
var d = new D(1)
d.__proto__ === D.prototype
D.prototype.__proto__ === C.prototype
// This is what `d.inc` actually does.
d.__proto__.__proto__.inc === C.prototype.inc
// Class variables
// No ES6 syntax sugar apparently:
// http://stackoverflow.com/questions/22528967/es6-class-variable-alternatives
C.c = 1
C.c === 1
// Because `D.__proto__ === C`.
D.c === 1
// Nothing makes this work.
d.c === undefined

सभी पूर्वनिर्धारित वस्तुओं के बिना सरलीकृत आरेख:

      __proto__
(C)<---------------(D)         (d)
| |                |           |
| |                |           |
| |prototype       |prototype  |__proto__
| |                |           |
| |                |           |
| |                | +---------+
| |                | |
| |                | |
| |                v v
|__proto__        (D.prototype)
| |                |
| |                |
| |                |__proto__
| |                |
| |                |
| | +--------------+
| | |
| | |
| v v
| (C.prototype)--->(inc)
|
v
Function.prototype

57
2018-06-18 19:48



मुझे नहीं पता कि आपको यह कहां मिला लेकिन यह सबसे स्पष्ट जवाब है! - tomasb
@ टोमासब धन्यवाद! "मुझे नहीं पता कि आपको यह कहां मिला": मैंने उन गतिशील भाषाओं में से कुछ को देखने के बाद, मैंने देखा कि उनकी कक्षा प्रणाली के बारे में सबसे महत्वपूर्ण बात यह है कि कैसे . लुकअप काम करता है (और डेटा की कितनी प्रतियां बनाई जाती हैं)। तो मैं उस बिंदु को समझने के लिए बाहर निकला। शेष Google + ब्लॉग पोस्ट + हाथ में एक जेएस दुभाषिया है। :) - Ciro Santilli 新疆改造中心 六四事件 法轮功
यह उत्तर उस अवधारणा की सच्ची और गहरी समझ को दिखाता है। बहुत बढ़िया! - Nir Smadar
मुझे अभी भी बिंदु नहीं मिलता है क्यों g.constructor === ऑब्जेक्ट क्योंकि आपने कहा था कि "4) जब आप f = new f करते हैं, तो नया f.constructor = f" भी सेट करता है। क्या आप मुझे और समझा सकते हैं? वैसे भी यह सबसे अच्छा जवाब है जिसे मैं ढूंढ रहा हूं। आपको बहुत - बहुत धन्यवाद! - nguyenng