जावास्क्रिप्ट के बारे में एक और स्मार्ट पुस्तक पढ़ने के बाद, मैंने इसमें विरासत को लागू करने के तरीकों को समझना शुरू किया। ठीक है, यह है कि, ज़ाहिर है, यह सभी के लिए स्पष्ट है कि एक वास्तविक, बड़े, प्रोजेक्ट में, कुछ लाइब्रेरी से एक फ़ंक्शन का उपयोग करना सबसे अच्छा है (उनमें से कई हैं), लेकिन आप वास्तव में समझना चाहते हैं कि यह सामान्य रूप से कैसे काम करता है।
मैंने यह देखने का निर्णय लिया कि इस विषय पर क्या है - सामान्य तौर पर, यह बेहतर होगा यदि मैं ऐसा नहीं करता हूं - कोई व्यक्ति कुछ पेजों के लिए अपनी बैसाखी के बारे में लेख लिखता है क्योंकि लाइब्रेरी का कार्य कुछ पसंद नहीं करता था, किसी को पूर्वज के लिए सुविधाजनक पहुंच लगती है। क्रम संख्या द्वारा। सामान्य तौर पर, बहुत सारे मज़े, बहुत सारे कोड, विवाद भी पर्याप्त हैं, लेकिन आधार केवल मौजूद नहीं है। और यह मुझे लग रहा था कि इसे ठीक करना अच्छा होगा।
1. तो, वास्तव में समस्या क्या है?
समस्या यह है कि जावास्क्रिप्ट में कोई परिचित विरासत नहीं है। क्लास कंस्ट्रक्टर बनाने के लिए अधिकतम जो किया जा सकता है:
function Class(){/* *}
और फिर, प्रोटोटाइप के माध्यम से, तरीकों, स्थिरांक और स्थिर चर जोड़ें जो सभी उदाहरणों के लिए समान होंगे।
Class.prototype = {}
यह ज्यादातर मामलों में पर्याप्त है, लेकिन कभी-कभी आप अधिक चाहते हैं।
2. और यदि आप वास्तव में चाहते हैं ...
... तो आप इसे लागू कर सकते हैं। क्लासिक तरीका इस तरह दिखता है:
function inherit_A(Child, Parent) { var F = function () { }; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.super = Parent.prototype; }
और आप इसका उपयोग भी कर सकते हैं:
$(document).ready(function () { function Man(name) { this.name = name } Man.prototype.say = function () { console.log("My name is " + this.name) } function Gentleman(name) { Man.call(this, name); } inherit_A(Gentleman, Man); });
सच है, मुझे उसके साथ एक छोटी सी समस्या है - आमतौर पर, एक प्रोटोटाइप बनाने के लिए, मैं ऑब्जेक्ट नोटेशन का उपयोग करता हूं, जैसा कि थोड़ा ऊपर दिखाया गया था:
Class.prototype = { }
और, इस विरासत के साथ, आप वास्तव में इस पद्धति का उपयोग नहीं करते हैं - या तो मेरे कार्य विरासत में दिए गए प्रोटोटाइप को पूरी तरह से मिटा देंगे, या विरासत में दिए गए प्रोटोटाइप मेरे कार्यों को पूरी तरह से मिटा देंगे। सौभाग्य से, आप एक अलग तरीके से वारिस कर सकते हैं।
3. विधि उन सभी को समर्पित है जो वस्तु शाब्दिक रूप से प्यार करते हैं
यहाँ वह है:
function inherit_B(Child, Parent) { var F = function () { }; F.prototype = Parent.prototype; var f = new F(); for (var prop in Child.prototype) f[prop] = Child.prototype[prop]; Child.prototype = f; Child.prototype.super = Parent.prototype; }
यह सिर्फ माता-पिता के प्रोटोटाइप से वारिस के प्रोटोटाइप के लिए सभी गुणों को लेता है और कॉपी करता है, इसलिए अब मेरी पसंदीदा वस्तु शाब्दिक रूप में काम करना चाहिए:
$(document).ready(function () { function Man(name) { this.name = name } Man.prototype = { constructor: Man, THOUGHTS: "wanna beer!", say: function () { console.log("My name is " + this.name + " and i think:'" + this.THOUGHTS + "'") } } function Gentleman(name, prefered_beverage) { Man.call(this, name); this.prefered_beverage = prefered_beverage; } Gentleman.prototype = { constructor: Gentleman, THOUGHTS: "it's teatime!" } inherit_B(Gentleman, Man) function Programmer(name, prefered_lang) { Gentleman.call(this, name, "Cofee"); this.prefered_lang = prefered_lang; } Programmer.prototype = { constructor: Programmer, THOUGHTS: "runtime error 138? wanna debug XD!" } inherit_B(Programmer, Gentleman) var man = new Man("Jack"); var gentleman = new Gentleman("John", "Orange pekoe"); var programmer = new Programmer("James", "C++"); man.say(); gentleman.say(); programmer.say(); });
और कंसोल मेरे साथ सहमत है:
sample.js:11 My name is Jack and i think:'wanna beer!' sample.js:11 My name is John and i think:'it's teatime!' sample.js:11 My name is James and i think:'runtime error 138? wanna debug!'
बहुत बढ़िया। अब एक काल्पनिक स्थिति की कल्पना करें जहां कई माता-पिता वर्ग हैं, और आपको उदाहरण के लिए, कुछ विधि को कॉल करने की आवश्यकता है जो 2-3 साल पहले ओवरलोड हो गई थी। ऐसी स्थिति में, निश्चित रूप से, आपके आवेदन की वास्तुकला पर करीब से नज़र डालना बेहतर है। अब मान लें कि सब कुछ वहाँ काम करता है, जैसा कि इरादा है, तो लिखने के लिए असुविधाजनक है, उदाहरण के लिए, इस तरह:
this.super.super.super.someMethod.apply(this)
4. लेकिन यह भी सॉल्व है
function inherit_C(Child, Parent) { var F = function () { }; F.prototype = Parent.prototype; var f = new F(); for (var prop in Child.prototype) f[prop] = Child.prototype[prop]; Child.prototype = f; Child.prototype[Parent.prototype.__class_name] = Parent.prototype; }
यह फ़ंक्शन पैरेंट प्रोटोटाइप के संदर्भ में चाइल्ड प्रोटोटाइप के लिए ऑब्जेक्ट जोड़ता है। इसे काम करने के लिए जैसा कि इसे करना चाहिए, प्रत्येक वर्ग के प्रोटोटाइप में एक फ़ील्ड जोड़ें
__class_name
उदाहरण के लिए, मान लीजिए कि बैडप्रोग्रामर वर्ग हमारी पदानुक्रम में दिखाई दिया, जिसे बस दूर के पूर्वजों के प्रोटोटाइप तक सुविधाजनक पहुंच की आवश्यकता थी। हम पिछले उदाहरण को थोड़ा संशोधित करते हैं:
$(document).ready(function () { function Man(name) { this.name = name } Man.prototype = { __class_name: "Man", constructor: Man, THOUGHTS: "wanna beer!", say: function () { console.log("My name is " + this.name + " and i think:'" + this.THOUGHTS + "'") } } function Gentleman(name, prefered_beverage) { Man.call(this, name); this.prefered_beverage = prefered_beverage; } Gentleman.prototype = { __class_name: "Gentleman", constructor: Gentleman, THOUGHTS: "it's teatime!" } inherit_C(Gentleman, Man) function Programmer(name, prefered_lang) { Gentleman.call(this, name, "Cofee"); this.prefered_lang = prefered_lang; } Programmer.prototype = { __class_name: "Programmer", constructor: Programmer, THOUGHTS: "runtime error 138? wanna debug XD!" } inherit_C(Programmer, Gentleman) function BadProgrammer(name) { Programmer.call(this, name, "brainfuck"); } BadProgrammer.prototype = { __class_name: "BadProgrammer", constructor: BadProgrammer, THOUGHTS: "runtime error 138? wanna debug XD!", say: function () { this.THOUGHTS = this.Man.THOUGHTS; this.Man.say.apply(this); } } inherit_C(BadProgrammer, Programmer) var man = new Man("Jack"); var gentleman = new Gentleman("John", "Orange pekoe"); var programmer = new Programmer("James", "C++"); var badprogrammer = new BadProgrammer("Jake"); man.say(); gentleman.say(); programmer.say(); badprogrammer.say(); });
बैडप्रोग्रामर वर्ग ने हमारी विकासवादी श्रृंखलाओं में बहुत पहले लिंक के विचारों का लाभ उठाया, और अब यह बिल्कुल नहीं सोच रहा है कि प्रोग्रामर आमतौर पर क्या सोचते हैं;)
My name is Jack and i think:'wanna beer!' My name is John and i think:'it's teatime!' My name is James and i think:'runtime error 138? wanna debug!' My name is Jake and i think:'wanna beer!'
5. और कुछ और
मैं किसी भी मामले में यह कल्पना नहीं कर सकता कि यह काम आ सकता है, लेकिन शायद किसी दिन, किसी को कई विरासत की आवश्यकता हो सकती है। इसे लागू करना भी काफी संभव है:
function inhertit_multiple(child) { for( var i = 1; i < arguments.length; ++i ) { var parent = arguments[i] for (var prop in parent.prototype) { if (!child.prototype[prop]) child.prototype[prop] = parent.prototype[prop]; } child.prototype[parent.prototype.__class_name] = parent.prototype; } }
पिछले संस्करण से बहुत अलग नहीं है।
यह दिखाने के लिए कि यह कैसे काम करता है, मैं एक और पूरी तरह से यथार्थवादी उदाहरण के साथ आया:
$(document).ready(function () { function Mammy() { this.mammy_message = "You Dont love me!" } Mammy.prototype = { __class_name: "Mammy", say_something_wise: function () { console.log(this.mammy_message) } } function Daddy() { this.daddy_message = "I just don't want to be a dad!" } Daddy.prototype = { __class_name: "Daddy", say_something_wise: function () { console.log(this.daddy_message) } } function Lad() { this.lad_message = "And i want a candy!"; Mammy.apply(this); Daddy.apply(this); } Lad.prototype = { __class_name: "Lad", say_something_wise: function () { this.Daddy.say_something_wise.call(this); this.Mammy.say_something_wise.call(this); console.log(this.lad_message); } } inhertit_multiple(Lad, Mammy, Daddy) var lad = new Lad(); lad.say_something_wise(); });
यदि आप इसे चलाते हैं, तो कंसोल कुछ ऐसा प्रदर्शित करेगा जैसा हम उम्मीद करते हैं
I just don't want to be a dad! You Dont love me! And i want candy!
कि यह सब कैसे काम करता है। मैंने सभी कोड और उदाहरण
यहां दिए - यह काम आएगा।
युपीडी। जैसा कि एक अच्छा व्यक्ति सही टिप्पणी करता है, पहले को छोड़कर सभी तरीकों में, Instof मूल वर्ग के उदाहरण के रूप में कक्षा को पहचानने से इनकार करता है। कई विरासत के साथ, यह खामी बनी रही, लेकिन अन्य मामलों के लिए, मैंने इसे समाप्त कर दिया।