मैं जावास्क्रिप्ट के पर्दे के पर्दे के पीछे समझने की कोशिश कर रहा हूं और वस्तुओं में निर्मित, विशेष रूप से ऑब्जेक्ट और फंक्शन और उनके बीच के संबंध को समझने में अटक गया।
यह जटिल है, गलतफहमी करना आसान है, और एक बहुत से शुरुआती जावास्क्रिप्ट किताबें गलत हैं, इसलिए पढ़ी गई हर चीज पर भरोसा न करें।
मैं 1990 के दशक में Microsoft के JS इंजन के मानकीकरण और मानकीकरण समिति में से एक था, और मैंने इस उत्तर को डालने में कई गलतियाँ कीं। (हालांकि मैंने 15 साल से इस पर काम नहीं किया है लेकिन मुझे माफ किया जा सकता है।) यह मुश्किल भरा काम है। लेकिन एक बार जब आप प्रोटोटाइप इनहेरिटेंस को समझ लेते हैं, तो यह सब समझ में आता है।
जब मैंने पढ़ा कि Array, String इत्यादि में निर्मित सभी ऑब्जेक्ट ऑब्जेक्ट से एक्सटेंशन (इनहेरिट की गई) हैं तो मैंने मान लिया कि ऑब्जेक्ट ऑब्जेक्ट में पहला बनाया गया है जो कि निर्मित होता है और बाकी ऑब्जेक्ट इससे प्राप्त होता है।
कक्षा-आधारित विरासत के बारे में जो कुछ भी आप जानते हैं, उसे फेंककर शुरू करें। JS प्रोटोटाइप आधारित विरासत का उपयोग करता है।
इसके बाद, सुनिश्चित करें कि आपके सिर में बहुत स्पष्ट परिभाषा है कि "विरासत" का क्या अर्थ है। C # या Java या C ++ जैसी OO भाषाओं का उपयोग करने वाले लोग सोचते हैं कि इनहेरिटेंस का अर्थ सबटाइपिंग है, लेकिन इनहेरिटेंस का मतलब सबटिप करना नहीं है। वंशानुक्रम का अर्थ है कि एक चीज के सदस्य दूसरी चीज के सदस्य भी हैं । यह नहीं है जरूरी मतलब उन चीजों के बीच एक subtyping रिश्ता होता है कि! टाइप थ्योरी में बहुत सी गलतफहमियां लोगों को यह अहसास नहीं होने का नतीजा है कि इसमें अंतर है।
लेकिन इसका कोई मतलब नहीं है जब आपको पता चले कि ऑब्जेक्ट केवल फ़ंक्शन द्वारा बनाए जा सकते हैं, लेकिन फिर फ़ंक्शन भी कुछ नहीं बल्कि फ़ंक्शन की वस्तुएं हैं।
यह केवल झूठ है। कुछ फ़ंक्शन के लिए कॉल करके कुछ ऑब्जेक्ट नहीं बनाए जाते हैं । कुछ वस्तुओं को जेएस रनटाइम द्वारा बिल्कुल भी नहीं बनाया जाता है। ऐसे अंडे हैं जो किसी भी चिकन द्वारा नहीं रखे गए थे । वे सिर्फ रनटाइम द्वारा बनाए गए थे जब यह शुरू हुआ था।new F
F
आइए बताते हैं कि नियम क्या हैं और शायद इससे मदद मिलेगी।
- हर ऑब्जेक्ट इंस्टेंस में एक प्रोटोटाइप ऑब्जेक्ट होता है।
- कुछ मामलों में जो प्रोटोटाइप हो सकते हैं
null
।
- यदि आप किसी ऑब्जेक्ट उदाहरण पर किसी सदस्य तक पहुँचते हैं, और ऑब्जेक्ट में वह सदस्य नहीं है, तो ऑब्जेक्ट उसके प्रोटोटाइप में ख़राब हो जाता है, या यदि प्रोटोटाइप शून्य है तो रुक जाता है।
prototype
एक वस्तु का सदस्य आमतौर पर है नहीं वस्तु के प्रोटोटाइप।
- बल्कि,
prototype
एक फंक्शन ऑब्जेक्ट F का सदस्य वह ऑब्जेक्ट है जो द्वारा बनाई गई ऑब्जेक्ट का प्रोटोटाइप बन जाएगा new F()
।
- कुछ कार्यान्वयन में, उदाहरणों को एक
__proto__
सदस्य मिलता है जो वास्तव में अपना प्रोटोटाइप देता है। (यह अब हटा दिया गया है। इस पर भरोसा न करें।)
- फंक्शन ऑब्जेक्ट्स को एक नई-नई डिफ़ॉल्ट ऑब्जेक्ट मिलती है,
prototype
जब उन्हें बनाया जाता है।
- एक फंक्शन ऑब्जेक्ट का प्रोटोटाइप निश्चित रूप से है
Function.prototype
।
चलो योग करो।
- का प्रोटोटाइप
Object
हैFunction.prototype
Object.prototype
ऑब्जेक्ट प्रोटोटाइप ऑब्जेक्ट है।
- का प्रोटोटाइप
Object.prototype
हैnull
- का प्रोटोटाइप
Function
है Function.prototype
- यह उन दुर्लभ स्थितियों में से एक है जहां Function.prototype
वास्तव में प्रोटोटाइप है Function
!
Function.prototype
फ़ंक्शन प्रोटोटाइप ऑब्जेक्ट है।
- का प्रोटोटाइप
Function.prototype
हैObject.prototype
मान लीजिए कि हम एक फ़ंक्शन फू बनाते हैं।
- का प्रोटोटाइप
Foo
है Function.prototype
।
Foo.prototype
फू प्रोटोटाइप वस्तु है।
- का प्रोटोटाइप
Foo.prototype
है Object.prototype
।
मान लीजिए हम कहते हैं new Foo()
- नई वस्तु का प्रोटोटाइप है
Foo.prototype
सुनिश्चित करें कि समझ में आता है। चलो इसे ड्रा करें। अंडाकार वस्तु उदाहरण हैं। किनारे या तो __proto__
अर्थ हैं "का प्रोटोटाइप", या prototype
अर्थ "की prototype
संपत्ति"।
सभी रनटाइम को उन सभी ऑब्जेक्ट्स को बनाना होगा और तदनुसार अपने विभिन्न गुणों को असाइन करना होगा। मुझे यकीन है कि आप देख सकते हैं कि यह कैसे किया जाएगा।
अब आइए एक उदाहरण देखें जो आपके ज्ञान का परीक्षण करता है।
function Car(){ }
var honda = new Car();
print(honda instanceof Car);
print(honda.constructor == Car);
यह क्या छपता है?
खैर, क्या instanceof
मतलब है? honda instanceof Car
इसका मतलब है " प्रोटोटाइप श्रृंखला Car.prototype
पर किसी भी वस्तु के बराबर है honda
?"
हाँ यही है। honda
प्रोटोटाइप है Car.prototype
, तो हम कर रहे हैं। यह सच छापता है।
दूसरे के बारे में क्या?
honda.constructor
मौजूद नहीं है इसलिए हम प्रोटोटाइप से सलाह लेते हैं, जो है Car.prototype
। जब Car.prototype
ऑब्जेक्ट बनाया गया था तो यह स्वचालित रूप से एक संपत्ति के constructor
बराबर दिया गया था Car
, इसलिए यह सच है।
अब इसका क्या?
var Animal = new Object();
function Reptile(){ }
Reptile.prototype = Animal;
var lizard = new Reptile();
print(lizard instanceof Reptile);
print(lizard.constructor == Reptile);
यह प्रोग्राम क्या छापता है?
फिर, lizard instanceof Reptile
इसका मतलब है " प्रोटोटाइप श्रृंखला Reptile.prototype
पर किसी भी वस्तु के बराबर है lizard
?"
हाँ यही है। lizard
प्रोटोटाइप है Reptile.prototype
, तो हम कर रहे हैं। यह सच छापता है।
अब, किस बारे में
print(lizard.constructor == Reptile);
आप सोच सकते हैं कि यह भी सच है, चूंकि lizard
निर्माण किया गया था , new Reptile
लेकिन आप गलत होंगे। कारण बताइए।
- क्या
lizard
कोई constructor
संपत्ति है? इसलिए हम प्रोटोटाइप को देखते हैं।
- का प्रोटोटाइप
lizard
है Reptile.prototype
, जो है Animal
।
- क्या
Animal
कोई constructor
संपत्ति है? नहीं, तो हम इसे प्रोटोटाइप के रूप में देखते हैं।
- का प्रोटोटाइप
Animal
है Object.prototype
, और Object.prototype.constructor
रनटाइम द्वारा बनाया गया है और इसके बराबर है Object
।
- इसलिए यह गलत है।
हमें Reptile.prototype.constructor = Reptile;
वहाँ किसी बिंदु पर कहना चाहिए था, लेकिन हमें याद नहीं था!
सुनिश्चित करें कि सभी आप के लिए समझ में आता है। यदि यह अभी भी भ्रमित है तो कुछ बक्से और तीर बनाएँ।
दूसरी बेहद भ्रमित करने वाली बात यह है, अगर मैं console.log(Function.prototype)
किसी फ़ंक्शन को प्रिंट करता हूं, लेकिन जब मैं प्रिंट console.log(Object.prototype)
करता हूं तो वह किसी ऑब्जेक्ट को प्रिंट करता है। Function.prototype
एक समारोह क्यों होता है जब इसे एक वस्तु माना जाता था?
फ़ंक्शन प्रोटोटाइप को एक फ़ंक्शन के रूप में परिभाषित किया जाता है, जिसे जब बुलाया जाता है, तो रिटर्न देता है undefined
। हम पहले से ही जानते हैं कि Function.prototype
यह Function
प्रोटोटाइप है, अजीब तरह से पर्याप्त है। इसलिए इसलिए Function.prototype()
कानूनी है, और जब आप इसे करते हैं, तो आप undefined
वापस आ जाते हैं। तो यह एक समारोह है।
Object
प्रोटोटाइप इस संपत्ति नहीं है, यह कॉल करने योग्य नहीं है। यह सिर्फ एक वस्तु है।
जब आप console.log(Function.prototype.constructor)
इसे फिर से एक समारोह है।
Function.prototype.constructor
बस Function
, जाहिर है। और Function
एक फंक्शन है।
अब आप इसे स्वयं बनाने के लिए किसी चीज़ का उपयोग कैसे कर सकते हैं (माइंड = ब्लो)।
आप यह सोच रहे हैं । यह आवश्यक है कि रनटाइम वस्तुओं का एक गुच्छा बनाता है जब यह शुरू होता है। ऑब्जेक्ट्स केवल लुकअप टेबल हैं जो ऑब्जेक्ट्स के साथ तार जोड़ते हैं। जब क्रम शुरू होता है, यह सब करना है कुछ दर्जन खाली वस्तुओं को बनाने, और फिर बताए शुरू है prototype
, __proto__
, constructor
, और इतने प्रत्येक वस्तु के गुणों पर जब तक वे ग्राफ है कि वे बनाने की जरूरत है सकते हैं।
यह उपयोगी होगा यदि आप उस आरेख को लेते हैं जो मैंने आपको ऊपर दिया था और constructor
इसमें किनारों को जोड़ दिया था। आप जल्दी से देखेंगे कि यह एक बहुत ही सरल ऑब्जेक्ट ग्राफ है और रनटाइम को इसे बनाने में कोई समस्या नहीं होगी।
एक अच्छा व्यायाम इसे स्वयं करना होगा। यहाँ, मैं आपको शुरू करूँगा। हम my__proto__
"के प्रोटोटाइप ऑब्जेक्ट" और myprototype
"प्रोटोटाइप संपत्ति " का मतलब करने के लिए उपयोग करेंगे ।
var myobjectprototype = new Object();
var myfunctionprototype = new Object();
myfunctionprototype.my__proto__ = myobjectprototype;
var myobject = new Object();
myobject.myprototype = myobjectprototype;
और इसी तरह। क्या आप बाकी प्रोग्राम को ऑब्जेक्ट के एक सेट का निर्माण करने के लिए भर सकते हैं जिसमें "वास्तविक" जावास्क्रिप्ट में निर्मित वस्तुओं के समान टोपोलॉजी है? यदि आप ऐसा करते हैं, तो आप पाएंगे कि यह बेहद आसान है।
जावास्क्रिप्ट में वस्तुएँ सिर्फ लुकअप टेबल हैं जो अन्य वस्तुओं के साथ तार जोड़ती हैं । बस! यहां कोई जादू नहीं है। आप अपने आप को गाँठों में बंधे हुए पा रहे हैं क्योंकि आप उन बाधाओं की कल्पना कर रहे हैं जो वास्तव में मौजूद नहीं हैं, जैसे कि प्रत्येक वस्तु को एक निर्माता द्वारा निर्मित किया जाना था।
फ़ंक्शंस बस एक अतिरिक्त क्षमता वाले ऑब्जेक्ट हैं: जिन्हें बुलाया जाना है। इसलिए अपने छोटे सिमुलेशन कार्यक्रम के माध्यम से जाएं और .mycallable
प्रत्येक वस्तु में एक संपत्ति जोड़ें जो इंगित करता है कि यह कॉल करने योग्य है या नहीं। यह इतना सरल है।
Function.prototype
एक फ़ंक्शन हो सकता है और आंतरिक क्षेत्र हो सकते हैं। तो नहीं, जब आप संरचना से गुजर रहे हैं तो प्रोटोटाइप फ़ंक्शन को निष्पादित नहीं करते हैं। अंत में याद रखें कि जावास्क्रिप्ट की व्याख्या करने वाला एक इंजन है, इसलिए ऑब्जेक्ट और फ़ंक्शन संभवतः इंजन के भीतर बनाए जाते हैं और जावास्क्रिप्ट से नहीं और विशेष संदर्भ जैसेFunction.prototype
औरObject.prototype
बस इंजन द्वारा एक विशेष तरीके से व्याख्या की जा सकती है।