शास्त्रीय पर प्रोटोटाइप विरासत के लाभ?


271

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



जवाबों:


560

मुझे पता है कि यह उत्तर 3 साल देर से है, लेकिन मुझे वास्तव में लगता है कि वर्तमान उत्तर इस बारे में पर्याप्त जानकारी नहीं देते हैं कि प्रोटोटाइप विरासत में शास्त्रीय विरासत से बेहतर कैसे है

पहले आइए देखें कि प्रोटोटाइप प्रोग्रामों के बचाव में जावास्क्रिप्ट प्रोग्रामर राज्य सबसे आम तर्क देते हैं (मैं इन तर्कों को उत्तर के वर्तमान पूल से ले रहा हूं):

  1. यह आसान है।
  2. यह शक्तिशाली है।
  3. यह छोटे, कम निरर्थक कोड की ओर जाता है।
  4. यह गतिशील है और इसलिए यह गतिशील भाषाओं के लिए बेहतर है।

अब ये तर्क सभी मान्य हैं, लेकिन किसी ने भी इसकी व्याख्या करने की जहमत नहीं उठाई। यह एक बच्चे को बताने जैसा है कि मैथ्स पढ़ना महत्वपूर्ण है। यकीन है कि यह है, लेकिन बच्चा निश्चित रूप से परवाह नहीं करता है; और आप यह कहकर मैथ्स जैसा बच्चा नहीं बना सकते कि यह महत्वपूर्ण है।

मुझे लगता है कि प्रोटोटाइप विरासत के साथ समस्या यह है कि इसे जावास्क्रिप्ट के परिप्रेक्ष्य से समझाया गया है। मुझे जावास्क्रिप्ट बहुत पसंद है, लेकिन जावास्क्रिप्ट में प्रोटोटाइप की विरासत गलत है। शास्त्रीय विरासत के विपरीत, प्रोटोटाइप विरासत के दो पैटर्न हैं:

  1. प्रोटोटाइप इनहेरिटेंस का प्रोटोटाइप पैटर्न।
  2. प्रोटोटाइप इनहेरिटेंस का निर्माता पैटर्न।

दुर्भाग्य से जावास्क्रिप्ट प्रोटोोटाइपल इनहेरिटेंस के कंस्ट्रक्टर पैटर्न का उपयोग करता है। इसका कारण यह है कि जब जावास्क्रिप्ट बनाया गया था, ब्रेंडन ईच (जेएस के निर्माता) चाहते थे कि यह जावा की तरह दिखे (जिसमें शास्त्रीय विरासत है):

और हम इसे जावा के एक छोटे भाई के रूप में धकेल रहे थे, उस समय विजुअल बेसिक जैसी पूरक भाषा के रूप में माइक्रोसॉफ्ट के भाषा परिवारों में C ++ था।

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

जावा जैसी भाषाओं के लोग, जिनमें शास्त्रीय विरासत होती है, और भी अधिक भ्रमित हो जाते हैं क्योंकि यद्यपि निर्माता वर्ग की तरह दिखते हैं, वे कक्षाओं की तरह व्यवहार नहीं करते हैं। जैसा कि डगलस क्रॉकफोर्ड ने कहा:

यह अप्रत्यक्ष रूप से भाषा को प्रशिक्षित प्रशिक्षित प्रोग्रामरों के लिए अधिक परिचित लगता है, लेकिन ऐसा करने में विफल रहा, जैसा कि हम बहुत कम राय से देख सकते हैं कि जावा प्रोग्रामर जावास्क्रिप्ट के हैं। जावास्क्रिप्ट का निर्माता पैटर्न शास्त्रीय भीड़ के लिए अपील नहीं करता था। इसने जावास्क्रिप्ट के वास्तविक प्रोटोटाइप स्वभाव को भी अस्पष्ट कर दिया। नतीजतन, बहुत कम प्रोग्रामर हैं जो भाषा का प्रभावी ढंग से उपयोग करना जानते हैं।

ये लो। सीधे घोड़े के मुंह से।

सच्चा प्रोटोटाइप इनहेरिटेंस

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

  1. एकदम नई वस्तु बनाएँ।
  2. किसी मौजूदा ऑब्जेक्ट को क्लोन करें और उसका विस्तार करें।

नोट: जावास्क्रिप्ट एक वस्तु क्लोन करने के दो तरीके प्रदान करता है - प्रतिनिधिमंडल और संयोजन । इसके बाद, मैं "क्लोन" शब्द का उपयोग विशेष रूप से प्रतिनिधिमंडल के माध्यम से विरासत का उल्लेख करने के लिए करूँगा, और शब्द "कॉपी" विशेष रूप से संघनन के माध्यम से विरासत का उल्लेख करने के लिए।

खूब बात की। आइए कुछ उदाहरण देखें। कहो मेरे पास त्रिज्या का एक चक्र है 5:

var circle = {
    radius: 5
};

हम इसके दायरे से क्षेत्र और वृत्त की परिधि की गणना कर सकते हैं:

circle.area = function () {
    var radius = this.radius;
    return Math.PI * radius * radius;
};

circle.circumference = function () {
    return 2 * Math.PI * this.radius;
};

अब मैं त्रिज्या का एक और चक्र बनाना चाहता हूं 10। ऐसा करने का एक तरीका होगा:

var circle2 = {
    radius: 10,
    area: circle.area,
    circumference: circle.circumference
};

हालाँकि जावास्क्रिप्ट एक बेहतर तरीका प्रदान करता है - प्रतिनिधिमंडल । ऐसा करने के लिए Object.createफ़ंक्शन का उपयोग किया जाता है:

var circle2 = Object.create(circle);
circle2.radius = 10;

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

अब आप पूछ सकते हैं, "यह कैसे सरल है? हर बार जब मैं एक नया सर्कल बनाना चाहता हूं तो मुझे क्लोन करना होगा circleऔर मैन्युअल रूप से इसे एक त्रिज्या असाइन करना होगा"। अच्छी तरह से समाधान आप के लिए भारी उठाने के लिए एक समारोह का उपयोग करने के लिए है:

function createCircle(radius) {
    var newCircle = Object.create(circle);
    newCircle.radius = radius;
    return newCircle;
}

var circle2 = createCircle(10);

वास्तव में आप इस सभी को एक एकल वस्तु शाब्दिक में जोड़ सकते हैं:

var circle = {
    radius: 5,
    create: function (radius) {
        var circle = Object.create(this);
        circle.radius = radius;
        return circle;
    },
    area: function () {
        var radius = this.radius;
        return Math.PI * radius * radius;
    },
    circumference: function () {
        return 2 * Math.PI * this.radius;
    }
};

var circle2 = circle.create(10);

जावास्क्रिप्ट में प्रोटोटाइप इनहेरिटेंस

यदि आप उपरोक्त कार्यक्रम में देखते हैं कि createफ़ंक्शन एक क्लोन बनाता है circle, radiusतो उसे एक नया असाइन करता है और फिर उसे वापस लौटाता है। यह वही है जो एक निर्माणकर्ता जावास्क्रिप्ट में करता है:

function Circle(radius) {
    this.radius = radius;
}

Circle.prototype.area = function () {
    var radius = this.radius;
    return Math.PI * radius * radius;
};

Circle.prototype.circumference = function () {         
    return 2 * Math.PI * this.radius;
};

var circle = new Circle(5);
var circle2 = new Circle(10);

जावास्क्रिप्ट में कंस्ट्रक्टर पैटर्न उल्टा प्रोटोटाइप पैटर्न है। एक ऑब्जेक्ट बनाने के बजाय आप एक कंस्ट्रक्टर बनाते हैं। newकीवर्ड बांधता thisका क्लोन करने के लिए निर्माता के अंदर सूचक prototypeनिर्माता के।

भ्रामक लगता है? ऐसा इसलिए है क्योंकि जावास्क्रिप्ट में कंस्ट्रक्टर पैटर्न अनावश्यक रूप से चीजों को जटिल करता है। यह वही है जो अधिकांश प्रोग्रामर को समझना मुश्किल है।

अन्य वस्तुओं से विरासत में मिली वस्तुओं के बारे में सोचने के बजाय, वे सोचते हैं कि कंस्ट्रक्टर अन्य कंस्ट्रक्टर्स से विरासत में मिला है और फिर पूरी तरह से भ्रमित हो गए हैं।

जावास्क्रिप्ट में निर्माण पैटर्न से बचा जाना चाहिए क्यों अन्य कारणों का एक पूरा गुच्छा है। आप उनके बारे में मेरे ब्लॉग पोस्ट में यहाँ पढ़ सकते हैं: कन्स्ट्रक्टर्स बनाम प्रोटोटाइप


तो शास्त्रीय विरासत से अधिक प्रोटोटाइप विरासत के लाभ क्या हैं? चलो फिर से सबसे आम तर्कों के माध्यम से चलते हैं, और बताते हैं कि क्यों

1. प्रोटोटाइप इनहेरिटेंस सरल है

सीएमएस ने अपने जवाब में कहा:

मेरी राय में, प्रोटोटाइप विरासत का प्रमुख लाभ इसकी सादगी है।

आइए विचार करें कि हमने अभी क्या किया। हमने एक ऐसी वस्तु बनाई, circleजिसकी त्रिज्या थी 5। फिर हमने इसे क्लोन किया और क्लोन को एक त्रिज्या दिया 10

इसलिए हमें केवल दो चीज़ों की ज़रूरत है जो कि प्रोटोटाइप इनहेरिटेंस काम करें:

  1. एक नई वस्तु बनाने का एक तरीका (जैसे वस्तु शाब्दिक)।
  2. मौजूदा वस्तु (जैसे Object.create) का विस्तार करने का एक तरीका ।

इसके विपरीत शास्त्रीय विरासत अधिक जटिल है। शास्त्रीय विरासत में आपके पास:

  1. क्लासेस।
  2. वस्तु।
  3. इंटरफेस।
  4. सार वर्ग।
  5. अंतिम कक्षाएं।
  6. वर्चुअल बेस क्लासेस।
  7. कंस्ट्रक्टर्स।
  8. विनाशकर्ता।

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

जैसा कि स्टीव येजे ने इसे अपने क्लासिकल ब्लॉग पोस्ट " पोर्ट्रेट ऑफ एन एनबीबी " में रखा है:

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

उसी अर्थ में कक्षाएं सिर्फ मेटा-डेटा हैं। वंशानुक्रम के लिए वर्गों की कड़ाई से आवश्यकता नहीं है। हालांकि कुछ लोग (आमतौर पर n00bs) के साथ काम करने के लिए कक्षाएं अधिक आरामदायक पाते हैं। यह उन्हें सुरक्षा की झूठी भावना देता है।

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

जैसा कि मैंने पहले कहा, कक्षाएं लोगों को सुरक्षा का गलत अर्थ देती हैं। उदाहरण के लिए आप NullPointerExceptionजावा में बहुत अधिक एस प्राप्त करते हैं तब भी जब आपका कोड पूरी तरह से सुपाठ्य हो। मुझे लगता है कि शास्त्रीय विरासत आमतौर पर प्रोग्रामिंग के रास्ते में मिलती है, लेकिन शायद यह सिर्फ जावा है। पायथन में एक अद्भुत शास्त्रीय विरासत प्रणाली है।

2. प्रोटोटाइप इनहेरिटेंस शक्तिशाली है

शास्त्रीय पृष्ठभूमि से आने वाले अधिकांश प्रोग्रामर्स का तर्क है कि शास्त्रीय विरासत प्रोटोटाइप की विरासत की तुलना में अधिक शक्तिशाली है क्योंकि इसमें निम्नलिखित हैं:

  1. निजी चर।
  2. एकाधिक वंशानुक्रम।

यह दावा झूठा है। हम पहले से ही जानते हैं कि जावास्क्रिप्ट निजी चर को बंद करने के माध्यम से समर्थन करता है , लेकिन कई विरासत के बारे में क्या? जावास्क्रिप्ट में वस्तुओं का केवल एक ही प्रोटोटाइप है।

सच्चाई यह है कि प्रोटोोटाइपल इनहेरिटेंस कई प्रोटोटाइप से विरासत में मिलने का समर्थन करती है। प्रोटोटाइप इनहेरिटेंस का सीधा सा मतलब है कि एक वस्तु दूसरी वस्तु से विरासत में मिली। वास्तव में प्रोटोटाइप विरासत को लागू करने के दो तरीके हैं :

  1. प्रत्यायोजन या विभेदक वंशानुक्रम
  2. क्लोनिंग या कॉन्टेनेटिव इनहेरिटेंस

हां जावास्क्रिप्ट केवल वस्तुओं को एक दूसरे ऑब्जेक्ट को सौंपने की अनुमति देता है। हालांकि यह आपको वस्तुओं की एक मनमानी संख्या के गुणों को कॉपी करने की अनुमति देता है। उदाहरण के लिए _.extendबस यही करता है।

बेशक कई प्रोग्रामर इसे सही उत्तराधिकार नहीं मानते हैं क्योंकि instanceofऔर isPrototypeOfअन्यथा कहते हैं। हालाँकि यह आसानी से हर वस्तु पर प्रोटोटाइप की एक सरणी को संग्रहीत करके सुधारा जा सकता है जो एक प्रोटोटाइप से विरासत में प्राप्त होता है:

function copyOf(object, prototype) {
    var prototypes = object.prototypes;
    var prototypeOf = Object.isPrototypeOf;
    return prototypes.indexOf(prototype) >= 0 ||
        prototypes.some(prototypeOf, prototype);
}

इसलिए प्रोटोटाइप विरासत में शास्त्रीय विरासत की तरह ही शक्तिशाली है। वास्तव में यह शास्त्रीय विरासत की तुलना में बहुत अधिक शक्तिशाली है क्योंकि प्रोटोटाइप विरासत में आप विभिन्न गुणों से हटने के लिए कौन से गुणों की नकल कर सकते हैं और कौन से गुण।

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

हालांकि जावास्क्रिप्ट में आपको सबसे अधिक संभावना हीरे की समस्या के बारे में कभी नहीं सुनाई देगी क्योंकि आप वास्तव में उन गुणों को नियंत्रित कर सकते हैं जिन्हें आप विरासत में लेना चाहते हैं और जिसमें से प्रोटोटाइप हैं।

3. प्रोटोटाइप इनहेरिटेंस कम निरर्थक है

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

एक तर्क यह हो सकता है कि शास्त्रीय विरासत के साथ अधिकांश प्रोग्रामिंग भाषाओं को सांख्यिकीय रूप से टाइप किया गया है और उपयोगकर्ता को स्पष्ट रूप से प्रकारों के विपरीत (हास्केल के विपरीत जो स्थैतिक टाइपिंग निहित है) की आवश्यकता होती है। इसलिए यह अधिक क्रिया कोड की ओर जाता है।

जावा इस व्यवहार के लिए कुख्यात है। मुझे स्पष्ट रूप से बॉब Nystrom को प्रैट परसर्स के बारे में अपने ब्लॉग पोस्ट में निम्नलिखित उपाख्यानों का उल्लेख करना याद है :

आपको जावा की "कृपया इसे यहाँ की नौकरशाही के चतुष्कोणीय स्तर पर हस्ताक्षर करें" से प्यार होगा।

फिर से, मुझे लगता है कि जावा केवल इतना ही चूसता है।

एक मान्य तर्क यह है कि सभी भाषाओं में शास्त्रीय विरासत का समर्थन नहीं होता है जो कई विरासतों का समर्थन करती हैं। फिर से जावा का ख्याल आता है। हां जावा में इंटरफेस है, लेकिन यह पर्याप्त नहीं है। कभी-कभी आपको वास्तव में कई विरासतों की आवश्यकता होती है।

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

4. प्रोटोटाइप इनहेरिटेंस गतिशील है

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

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

निष्कर्ष

प्रोटोटाइप वंशानुक्रम मायने रखता है। जावास्क्रिप्ट प्रोग्रामर्स को शिक्षित करना महत्वपूर्ण है क्यों कि प्रोटोटाइप इनहेरिटेंस के प्रोटोटाइप पैटर्न के पक्ष में प्रोटोटाइप उत्तराधिकार के निर्माता पैटर्न को छोड़ देना चाहिए।

हमें जावास्क्रिप्ट को सही ढंग से पढ़ाना शुरू करने की आवश्यकता है और इसका मतलब है कि नए प्रोग्रामर को दिखाना है कि कंस्ट्रक्टर पैटर्न के बजाय प्रोटोटाइप पैटर्न का उपयोग करके कोड कैसे लिखना है।

न केवल प्रोटोटाइप पैटर्न का उपयोग करके प्रोटोटाइप विरासत की व्याख्या करना आसान होगा, बल्कि यह बेहतर प्रोग्रामर भी बनाएगा।

अगर आपको यह उत्तर पसंद आया है तो आपको " Why Prototypal Inheritance Matters " पर मेरा ब्लॉग पोस्ट भी पढ़ना चाहिए । मेरा विश्वास करो, आप निराश नहीं होंगे।


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

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

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

25
आप शब्द क्लोन का बहुत उपयोग कर रहे हैं , जो कि बस गलत है। Object.createनिर्दिष्ट प्रोटोटाइप के साथ नई वस्तु बना रहा है। आपके शब्दों का चयन यह धारणा देता है कि प्रोटोटाइप क्लोन हो गया है।
पावेल होराल

7
@Aadit: वास्तव में इतना रक्षात्मक होने की कोई आवश्यकता नहीं है। आपका जवाब बहुत विस्तृत और वोट के योग्य है। मैं सुझाव नहीं दे रहा था कि "जुड़ा हुआ" "क्लोन" के लिए एक ड्रॉप-इन प्रतिस्थापन होना चाहिए, लेकिन यह अधिक उचित रूप से किसी वस्तु और प्रोटोटाइप के बीच संबंध का वर्णन करता है जो इसे विरासत में मिला है, चाहे आप शब्द की अपनी परिभाषा का दावा करें "क्लोन " या नहीं। इसे बदलें या इसे न बदलें, यह पूरी तरह से आपकी पसंद है।
एंडी ई

42

मुझे वास्तव में प्रश्न इनलाइन का उत्तर देने की अनुमति दें।

प्रोटोटाइप विरासत में निम्नलिखित गुण हैं:

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

हालांकि इसके निम्नलिखित नुकसान हैं:

  1. एक प्रोटोटाइप भाषा की जाँच करना असंभव नहीं है, लेकिन यह बहुत, बहुत मुश्किल है। प्रोटोटाइप भाषाओं की अधिकांश "टाइप चेकिंग" शुद्ध रन-टाइम "डक टाइपिंग" -स्टाइल चेक है। यह सभी वातावरणों के लिए उपयुक्त नहीं है।
  2. स्थैतिक (या, अक्सर, यहां तक ​​कि गतिशील!) विश्लेषण द्वारा अनुकूलन विधि प्रेषण जैसी चीजों को करना मुश्किल है। यह कर सकते हैं (मैं तनाव: कर सकते हैं ) बहुत आसानी से बहुत अक्षम हो।
  3. इसी तरह से ऑब्जेक्ट क्रिएशन (और आमतौर पर) एक प्रोटोटाइप भाषा में बहुत धीमा हो सकता है, क्योंकि यह एक अधिक पारंपरिक वर्ग / ऑब्जेक्ट डाइकोटॉमी स्कीम में हो सकता है।

मुझे लगता है कि आप ऊपर की पंक्तियों के बीच पढ़ सकते हैं और पारंपरिक वर्ग / वस्तु योजनाओं के संगत फायदे और नुकसान के साथ आ सकते हैं। बेशक, प्रत्येक क्षेत्र में और अधिक हैं तो मैं बाकी लोगों को जवाब देने के लिए छोड़ दूंगा।


1
अरे देखो, एक संक्षिप्त जवाब जो fanboy नहीं है। वास्तव में यह प्रश्न के लिए शीर्ष उत्तर थे।
सिलिकॉनट्रस्टस्टार

हमारे पास आज डायनामिक जस्ट-इन-टाइम कंपाइलर हैं जो कोड को संकलित कर सकते हैं, जबकि कोड प्रत्येक अनुभाग के लिए कोड के विभिन्न टुकड़े बना रहा है। जावास्क्रिप्ट वास्तव में रूबी या पायथन की तुलना में तेज़ है जो इस वजह से शास्त्रीय कक्षाओं का उपयोग करते हैं कि भले ही आप प्रोटोटाइप का उपयोग करें क्योंकि इसके अनुकूलन पर बहुत सारे काम किए गए हैं।
aoeu256

28

आईएमओ प्रोटोटाइप प्रोटोटाइप की प्रमुख लाभ इसकी सादगी है।

भाषा का प्रोटोटाइप प्रकृति उन लोगों को भ्रमित कर सकती है जो शास्त्रीय रूप से प्रशिक्षित हैं, लेकिन यह पता चलता है कि वास्तव में यह वास्तव में सरल और शक्तिशाली अवधारणा है, अंतर विरासत

आपको वर्गीकरण करने की आवश्यकता नहीं है , आपका कोड छोटा है, कम निरर्थक, वस्तुओं को अन्य, अधिक सामान्य वस्तुओं से विरासत में मिला है।

यदि आपको लगता है कि प्रोटोटाइप आप जल्द ही नोटिस करेंगे कि आपको कक्षाओं की आवश्यकता नहीं है ...

निकट भविष्य में प्रोटोटाइप विरासत में बहुत अधिक लोकप्रिय हो जाएगा, ECMAScript 5 वें संस्करण विनिर्देश ने Object.createविधि पेश की , जो आपको एक नए ऑब्जेक्ट उदाहरण का उत्पादन करने की अनुमति देता है जो वास्तव में सरल तरीके से दूसरे से विरासत में मिलता है:

var obj = Object.create(baseInstance);

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


11
"आपका कोड छोटा है, कम निरर्थक ...", क्यों? मैंने "अंतर विरासत" के लिए विकिपीडिया लिंक पर एक नज़र डाली है और इन दावों का समर्थन करने के लिए कुछ भी नहीं है। शास्त्रीय विरासत में बड़ा, अधिक निरर्थक कोड क्यों होगा?
नोएल अब्राहम

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

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

प्रोटोटाइप भयानक हैं, IMO। मैं हास्केल जैसी कार्यात्मक भाषा बनाने के बारे में सोच रहा हूं ... लेकिन इसके बजाय मैं हर चीज को प्रोटोटाइप पर आधारित करूँगा। योग को सामान्य करने के बजाय, और "फोल्ड" करने के लिए फैक्टोरियल आपको उत्पाद बनाने के लिए योग फ़ंक्शन के प्रोटोटाइप और + की जगह * और 0 को 1 से बदलना चाहिए। मैं "मोनाड्स" को प्रोटोटाइप के रूप में समझाऊंगा जो कि "फिर" को वादों / कॉलबैक से बदल देता है और फ़्लैटबॉल के साथ "तब" का एक पर्याय बन जाता है। मुझे लगता है कि प्रोटोटाइप कार्यात्मक प्रोग्रामिंग को जन-जन तक पहुँचाने में मदद कर सकता है।
aoeu256

11

वास्तव में दो तरीकों के बीच चयन करने के लिए बहुत कुछ नहीं है। समझने के लिए मूल विचार यह है कि जब जावास्क्रिप्ट इंजन को पढ़ने के लिए किसी ऑब्जेक्ट की संपत्ति दी जाती है, तो यह पहले उदाहरण की जांच करता है और यदि वह संपत्ति गायब है, तो यह प्रोटोटाइप श्रृंखला की जांच करता है। यहाँ एक उदाहरण है जो प्रोटोटाइप और शास्त्रीय के बीच के अंतर को दर्शाता है:

मूलरूप का

var single = { status: "Single" },
    princeWilliam = Object.create(single),
    cliffRichard = Object.create(single);

console.log(Object.keys(princeWilliam).length); // 0
console.log(Object.keys(cliffRichard).length); // 0

// Marriage event occurs
princeWilliam.status = "Married";

console.log(Object.keys(princeWilliam).length); // 1 (New instance property)
console.log(Object.keys(cliffRichard).length); // 0 (Still refers to prototype)

उदाहरण के तरीकों के साथ शास्त्रीय (अक्षम है क्योंकि प्रत्येक उदाहरण में यह अपनी संपत्ति है)

function Single() {
    this.status = "Single";
}

var princeWilliam = new Single(),
    cliffRichard = new Single();

console.log(Object.keys(princeWilliam).length); // 1
console.log(Object.keys(cliffRichard).length); // 1

कुशल शास्त्रीय

function Single() {
}

Single.prototype.status = "Single";

var princeWilliam = new Single(),
    cliffRichard = new Single();

princeWilliam.status = "Married";

console.log(Object.keys(princeWilliam).length); // 1
console.log(Object.keys(cliffRichard).length); // 0
console.log(cliffRichard.status); // "Single"

जैसा कि आप देख सकते हैं, चूंकि शास्त्रीय शैली में घोषित "वर्गों" के प्रोटोटाइप में हेरफेर करना संभव है, इसलिए प्रोटोटाइप विरासत का उपयोग करने का वास्तव में कोई लाभ नहीं है। यह शास्त्रीय पद्धति का एक सबसेट है।


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

2

वेब डेवलपमेंट: प्रोटोटाइप इनहेरिटेंस बनाम क्लासिकल इनहेरिटेंस

http://chamnapchhorn.blogspot.com/2009/05/prototypal-inheritance-vs-classical.html

शास्त्रीय बनाम प्रोटोटाइप विरासत - ढेर अतिप्रवाह

शास्त्रीय बनाम प्रोटोटाइप विरासत


20
मुझे लगता है कि लिंक को चिपकाने के बजाय लिंक की सामग्री को संक्षेप में प्रस्तुत करना बेहतर है (कुछ ऐसा जो मैं खुद करता था), जब तक कि उसका दूसरा एसओ लिंक न हो। ऐसा इसलिए है क्योंकि लिंक / साइट नीचे जाती हैं और आप प्रश्न की प्रतिक्रिया को ढीला कर देते हैं, और यह संभावित रूप से खोज परिणामों को प्रभावित करता है।
जेम्स वेस्टगेट

पहली कड़ी इस सवाल का जवाब नहीं देती कि प्रोटोटाइप की विरासत क्यों है ? यह बस इसका वर्णन करता है।
विबेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.