ECMAScript विरासत तंत्र कार्यान्वयन
- पिछला पृष्ठ विरासत व्यवस्था का उदाहरण
- अगला पृष्ठ JavaScript उच्च स्तरीय पाठ्यक्रम
विरासत प्रक्रिया का कार्यान्वयन
ECMAScript में विरासत प्रक्रिया को लागू करने के लिए, आप किसी भी विरासत करने वाले आधार-क्लास से शुरू कर सकते हैं। सभी डेवलपर के द्वारा परिभाषित क्लास आधार-क्लास के रूप में इस्तेमाल किए जा सकते हैं। सुरक्षा कारणों से, स्थानीय क्लास और होस्ट क्लास को आधार-क्लास के रूप में नहीं इस्तेमाल किया जा सकता है, इससे बचता है कि सार्वजनिक रूप से अधिकृत ब्राउज़र कोड को एक्सेस किया जा सके, जो शातिराचारी उद्देश्यों के लिए इस्तेमाल किया जा सकता है।
आधार-क्लास चुनने के बाद, इसके उपक्लास को बनाना संभव होता है। आधार-क्लास का इस्तेमाल करना या नहीं करना आपकी विन्यास है। कभी-कभी आप एक ऐसा आधार-क्लास बनाना चाहते हैं जो सीधे इस्तेमाल नहीं किया जा सकता है, जो केवल उपक्लास को सामान्य फंक्शन प्रदान करने के लिए है। इस स्थिति में, आधार-क्लास अभिकल्पन-क्लास के रूप में देखा जाता है।
यद्यपि ECMAScript अन्य भाषाओं की तरह से साबित उच्च-क्लास को गंभीर रूप से परिभाषित नहीं करता है, लेकिन कभी-कभी यह कुछ ऐसे क्लासों को बनाता है जो नहीं इस्तेमाल किए जाने चाहिए। आमतौर पर, इस तरह के क्लासों को अभिकल्पन-क्लास कहा जाता है।
बनाए गए उपक्लास सभी विशेषताओं और विधियों को उच्च-क्लास से विरासत करेगा, जिसमें निर्माण कार्यक्रम और विधि का कार्यान्वयन भी शामिल है। याद रखें कि सभी विशेषताएं और विधियां सार्वजनिक हैं, इसलिए उपक्लास इन विधियों को सीधे एक्सेस कर सकते हैं। उपक्लास उच्च-क्लास में नहीं होने वाली नई विशेषताएं और विधियां जोड़ सकते हैं, या उच्च-क्लास की विशेषताओं और विधियों को ओवरराइड कर सकते हैं।
विरासत के तरीके
अन्य किसी फ़ंक्शन के समान, ECMAScript विरासत करने के तरीके एकल नहीं हैं। यह इसलिए है कि JavaScript में विरासत के तंत्र को स्पष्ट रूप से निर्धारित नहीं किया गया है, बल्कि उसके साथ नकल करके बनाया गया है। इसका मतलब है कि सभी विरासत के विवरण एकमात्र व्याख्याकार के द्वारा नहीं हैं। डेवलपर को सबसे उपयुक्त विरासत के तरीके का निर्णय करने का अधिकार है।
अब, आपको कुछ विशिष्ट विरासत के तरीकों को पेश किया जाएगा。
ऑब्जेक्ट मास्करेडिंग
आरंभिक ECMAScript के निर्माण के दौरान, ऑब्जेक्ट मास्करेडिंग (object masquerading) को निर्माण करने की कोई योजना नहीं थी। यह विकसित हुआ जब डेवलपरों ने फ़ंक्शन के काम के तरीके को समझना शुरू किया, विशेष रूप से this की अवधारणा का उपयोग करके फ़ंक्शन परिवेश में कैसे इस्तेमाल किया जाता है।
इसका सिद्धांत नीचे दिया गया है: निर्माण फ़ंक्शन this की द्वारा सभी गुणों और तरीकों को असीमित मान दिया जाता है (यानी, वर्ग के घोषणा के तरीके से निर्माण फ़ंक्शन के तरीके से)। निर्माण फ़ंक्शन केवल फ़ंक्शन है, इसलिए ClassA के निर्माण फ़ंक्शन को ClassB के तरीके के रूप में उपयोग कर सकते हैं, और इसे बुलाया जा सकता है। ClassB ClassA के निर्माण फ़ंक्शन में परिभाषित गुणों और तरीकों को प्राप्त करेगा। उदाहरण के लिए, नीचे दिए गए तरीके से ClassA और ClassB को परिभाषित किया जा सकता है:
function ClassA(sColor) { this.color = sColor; this.sayColor = function () { alert(this.color); }; } function ClassB(sColor) { }
याद है? अवधारणा this के द्वारा निर्माण फ़ंक्शन के रूप में संदर्भित होता है। लेकिन इस तरीके में, this का संदर्भ इस तरीके के उपरीयोग के उपरीयोग के उपरीयोग के उपरीयोग को दिया जाता है। यह सिद्धांत यह है कि ClassA को निर्माण फ़ंक्शन के रूप में उपयोग करके विरासत के तंत्र को स्थापित करने के लिए, नहीं कि निर्माण फ़ंक्शन के रूप में। नीचे दिए गए निर्माण फ़ंक्शन ClassB का उपयोग करके विरासत के तंत्र को स्थापित करने के लिए इसे किया जा सकता है:
function ClassB(sColor) { this.newMethod = ClassA; this.newMethod(sColor); delete this.newMethod; }
इस कोड में, ClassA को नए तरीके newMethod दिया गया है (याद रखें, फ़ंक्शन नाम केवल इसके उपरीयोग का संदर्भ है)। फिर इस तरीके को बुलाया गया है, जिसे ClassB के निर्माण फ़ंक्शन के पारामीटर sColor को भेजा गया है। आखिरी लाइन में ClassA के लिंक को मिटाया गया है, इस तरह इसे आगे भी बुलाया नहीं जा सकता।
सभी नए गुण और तरीकों को नए तरीके को मिटाने के बाद परिभाषित करना चाहिए। अन्यथा, उपवर्ग के संबंधित गुणों और तरीकों को ओवरराइड कर सकते हैं:
function ClassB(sColor, sName) { this.newMethod = ClassA; this.newMethod(sColor); delete this.newMethod; this.name = sName; this.sayName = function () { alert(this.name); }; }
पहले के कोड के प्रभावी होने की पुष्टि करने के लिए, नीचे दिए गए उदाहरण को चलाया जा सकता है:
var objA = new ClassA("blue"); var objB = new ClassB("red", "John"); objA.sayColor(); //आउटपुट "blue" objB.sayColor(); //आउटपुट "red" objB.sayName(); //आउटपुट "John"
ऑब्जेक्ट मास्करेडिंग बहुवरण को प्रदर्शित कर सकता है
इसके अलावा, ऑब्जेक्ट मास्करेडिंग बहुवरण का समर्थन करता है। अर्थात, एक वर्ग कई उपवर्गों को आगे ले करके चाह सकता है। यूएमएल के द्वारा बहुवरण के तंत्र को नीचे दिए गए चित्र में देखा जा सकता है:

उदाहरण में, यदि दो वर्ग ClassX और ClassY हैं, और ClassZ इन दोनों को आगे ले करके चाहता है, तो नीचे दिए गए कोड का उपयोग कर सकता है:
function ClassZ() { this.newMethod = ClassX; this.newMethod(); delete this.newMethod; this.newMethod = ClassY; this.newMethod(); delete this.newMethod; }
यहाँ एक नाकामी है, यदि दो कक्षाएँ ClassX और ClassY एक साथ गुण या विधि के नाम के साथ हैं, तो ClassY की अधिकता है क्योंकि यह पीछे की कक्षा से विरासत करती है. इसके अलावा, वस्तु के अभिनय के माध्यम से बहुविरासत के लिए आसानी से व्यवस्था की जा सकती है.
इस विधि के लोकप्रियता के कारण, ECMAScript का तीसरा संस्करण Function वस्तु को दो नई विधियाँ जोड़ा, जो call() और apply() हैं.
call() विधि
call() विधि शास्त्रीय वस्तु के अभिनय के सबसे मिलते-जुलते विधि है. इसका पहला पारामीटर this के लिए वस्तु के रूप में उपयोग किया जाता है. अन्य सभी पारामीटर सीधे फ़ंक्शन को पास किए जाते हैं. उदाहरण के लिए:
function sayColor(sPrefix,sSuffix) { alert(sPrefix + this.color + sSuffix); }; var obj = new Object(); obj.color = "blue"; sayColor.call(obj, "The color is ", "a very nice color indeed.");
इस उदाहरण में, फ़ंक्शन sayColor() वस्तु के बाहर परिभाषित है, यदि यह किसी वस्तु के साथ नहीं है, तो भी इसे this की ओर देखा जा सकता है. वस्तु obj का color गुण blue है. call() विधि को आदेश देते समय, पहला पारामीटर obj है, जिसका अर्थ है कि sayColor() फ़ंक्शन के भीतर this की गुण को obj को देना है. दूसरा और तीसरा पारामीटर शब्द. वे sayColor() फ़ंक्शन के पारामीटर sPrefix और sSuffix से मेल खाते हैं, अंत में बने संदेश "The color is blue, a very nice color indeed." प्रदर्शित होगा.
इस विधि को आरिज़ विरासत के वस्तु के लिए उपयोग करने के लिए, केवल पहले तीन लेन्स के लिए असामान्य, आदेश, और हटाने के कोड को बदलें:
function ClassB(sColor, sName) { //this.newMethod = ClassA; //this.newMethod(color); //delete this.newMethod; ClassA.call(this, sColor); this.name = sName; this.sayName = function () { alert(this.name); }; }
यहाँ, हमें ClassA में कीवर्ड this को नवीनतम बनाने की जरूरत है, इसलिए this पहला पारामीटर है. दूसरा पारामीटर sColor दोनों कक्षाओं के लिए अद्वितीय पारामीटर है.
apply() विधि
apply() विधि के दो पारामीटर होते हैं, जो this के लिए वस्तु और फ़ंक्शन को पास करने वाले पारामीटरों के आयत्त हैं. उदाहरण के लिए:
function sayColor(sPrefix,sSuffix) { alert(sPrefix + this.color + sSuffix); }; var obj = new Object(); obj.color = "blue"; sayColor.apply(obj, new Array("The color is ", "a very nice color indeed."));
इस उदाहरण पहले के उदाहरण के समान है, केवल इस बात के लिए कि अब apply() विधि को आदेश दिया जा रहा है। apply() विधि को आदेश देते समय, पहला पैरामीटर अभी भी obj है, इसलिए obj को sayColor() फ़ंक्शन के इस्तेमाल में this की मान देना है। दूसरा पैरामीटर दो शब्दों का एक एक्सेस है, जो sayColor() फ़ंक्शन के sPrefix और sSuffix पैरामीटरों से मेल खाता है, अंत में बनाया गया संदेश "The color is blue, a very nice color indeed." है, जो दिखाया जाएगा。
यह विधि आगे के तीन लाइनों के असामान्यता, आदेश, नई विधि को हटाने और नई विधि को परिवर्तन करने के लिए भी इस्तेमाल की जाती है:
function ClassB(sColor, sName) { //this.newMethod = ClassA; //this.newMethod(color); //delete this.newMethod; ClassA.apply(this, new Array(sColor)); this.name = sName; this.sayName = function () { alert(this.name); }; }
इसी तरह, पहला पैरामीटर अभी भी this है, दूसरा पैरामीटर केवल एक मूल्य रंग के एक सदस्य का एक एक्सेस है। ClassB के पूरे arguments ऑब्जेक्ट को apply() विधि को दूसरा पैरामीटर के रूप में पास किया जा सकता है:
function ClassB(sColor, sName) { //this.newMethod = ClassA; //this.newMethod(color); //delete this.newMethod; ClassA.apply(this, arguments); this.name = sName; this.sayName = function () { alert(this.name); }; }
स्वाभाविक है, केवल जबकि मूल क्लास में पैरामीटर की क्रमवार शृंखला उपकरण क्लास में पैरामीटर की क्रमवार शृंखला से पूरी तरह से मेल खाती है, तभी पैरामीटर ऑब्जेक्ट को पास किया जा सकता है। अन्यथा, एक अलग एक्सेस को बनाना आवश्यक है, जिसमें सही क्रम में पैरामीटर रखे गए हों। इसके अलावा call() विधि का उपयोग किया जा सकता है。
प्रोटोटाइप चेन (prototype chaining)
इस तरह का विरासत ECMAScript में मूल रूप से प्रोटोटाइप चेन के लिए इस्तेमाल किया जाता है। पिछले अध्याय में क्लास को प्रोटोटाइप तरीके से परिभाषित करने के बारे में बताया गया है। प्रोटोटाइप चेन इस तरीके को विस्तारित करता है और विरासत प्रक्रिया को एक दिलचस्प तरीके से साधारण करता है。
पिछले अध्याय में सीखा गया है, prototype ऑब्जेक्ट एक मॉडल है, जिसके आधार पर सभी इनस्टेंस बनाए जाते हैं। कुल मिलाकर, prototype ऑब्जेक्ट की किसी भी गुण और विधि को उस क्लास के सभी इनस्टेंस को पास किया जाता है। प्रोटोटाइप चेन इस फ़ंक्शन का उपयोग करके विरासत प्रक्रिया को साधारण करता है。
यदि प्रोटोटाइप तरीके से पहले की उदाहरण को क्लास को पुनर्विन्यास किया जाए, तो उनका रूप निम्नलिखित बन जाएगा:
function ClassA() { } ClassA.prototype.color = "blue"; ClassA.prototype.sayColor = function () { alert(this.color); }; function ClassB() { } ClassB.prototype = new ClassA();
原型方式的神奇之处在于突出显示的蓝色代码行。这里,把 ClassB 的 prototype 属性设置成 ClassA 的实例。这很有意思,因为想要 ClassA 的所有属性和方法,但又不想逐个将它们 ClassB 的 prototype 属性。还有比把 ClassA 的实例赋予 prototype 属性更好的方法吗?
注意:调用 ClassA 的构造函数,没有给它传递参数。这在原型链中是标准做法。要确保构造函数没有任何参数。
与对象冒充相似,子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。为什么?因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。所以,为 ClassB 类添加 name 属性和 sayName() 方法的代码如下:
function ClassB() { } ClassB.prototype = new ClassA(); ClassB.prototype.name = ""; ClassB.prototype.sayName = function () { alert(this.name); };
इस स्क्रिप्ट को चलाकर इस भाग को परीक्षण कर सकते हैं:
var objA = new ClassA(); var objB = new ClassB(); objA.color = "blue"; objB.color = "red"; objB.name = "John"; objA.sayColor(); objB.sayColor(); objB.sayName();
इसके अलावा, प्रोटोटाइप लिंक में instanceof ऑपरेटर के रूप-रूप के रूप-रूप का अनुसरण भी अनूठा है. ClassB के सभी इंस्टेंस के लिए instanceof ClassA और ClassB दोनों को true देता है. उदाहरण के लिए:
var objB = new ClassB(); alert(objB instanceof ClassA); //आउटपुट "true" alert(objB instanceof ClassB); //आउटपुट "true"
एससीमैट्रीक्स के अल्पस्पष्ट टाइपिंग दुनिया में, यह अत्यंत उपयोगी औजार है, हालांकि ऑब्जैक्ट के छलांग लगाने के समय इसका इस्तेमाल नहीं किया जा सकता.
प्रोटोटाइप लिंक का दोष है कि यह बहु-विरासत का समर्थन नहीं करता. याद रखें, प्रोटोटाइप लिंक प्रोटोटाइप प्रॉपर्टी को दूसरी प्रकार के ऑब्जैक्ट से प्रदर्शित करता है.
मिश्रित तरीका
यह विरासत तरीका कोन्स्ट्रक्टर फ़ंक्शन से क्लास को परिभाषित करता है, न कि किसी भी प्रोटोटाइप के साथ. ऑब्जैक्ट का छलांग लगाने का मुख्य मसला है कि इसे कोन्स्ट्रक्टर तरीका से ही इस्तेमाल करना होता है, यह सबसे अच्छा विकल्प नहीं है. हालांकि, यदि प्रोटोटाइप लिंक का इस्तेमाल किया जाए, तो पैरामीटरों से युक्त कोन्स्ट्रक्टर का इस्तेमाल नहीं किया जा सकता. डेवलपर कैसे चुना जाए? जवाब साधारण है, दोनों का इस्तेमाल करें.
पिछले अध्याय में, हमने बताया है कि कलाकृति को बनाने का सबसे अच्छा तरीका है कि कार्यक्रम गुण को संरचना कार्यक्रम में निर्माण करें और विधि को प्रोटोटाइप में निर्माण करें।यह तरीका विरासत व्यवस्था के लिए भी लागू होता है, ऑब्जेक्ट के रूप में संरचना कार्यक्रम के गुण को विरासत करें और प्रोटोटाइप वस्तु के विधि को प्रोटोटाइप लाइन से विरासत करें।इन दोनों तरीकों से पुनर्लिखित पूर्व उदाहरण को नीचे दिया गया है:}}
function ClassA(sColor) { this.color = sColor; } ClassA.prototype.sayColor = function () { alert(this.color); }; function ClassB(sColor, sName) { ClassA.call(this, sColor); this.name = sName; } ClassB.prototype = new ClassA(); ClassB.prototype.sayName = function () { alert(this.name); };
इस उदाहरण में, विरासत व्यवस्था दो ब्लू शोर्ट कोड द्वारा कार्यान्वित की गई है।पहले ब्लू शोर्ट कोड में ClassB निर्माण कार्यक्रम में ClassA वर्ग के sColor गुण को ऑब्जेक्ट के रूप में विरासत किया गया है।दूसरे ब्लू शोर्ट कोड में ClassA वर्ग के विधि को प्रोटोटाइप लाइन से विरासत किया गया है।इस प्रकार के मिश्रण में प्रोटोटाइप लाइन का इस्तेमाल करके instanceof ऑपरेटर अभी भी सही तरीके से काम करता है。
नीचे दिए गए उदाहरण में इस कोड का परीक्षण किया गया है:
var objA = new ClassA("blue"); var objB = new ClassB("red", "John"); objA.sayColor(); //आउटपुट "blue" objB.sayColor(); //आउटपुट "red" objB.sayName(); //आउटपुट "John"
- पिछला पृष्ठ विरासत व्यवस्था का उदाहरण
- अगला पृष्ठ JavaScript उच्च स्तरीय पाठ्यक्रम