जावास्क्रिप्ट में प्रोटोटाइप प्रोग्रामिंग का उपयोग कब करें


15

मैंने निम्नलिखित तरीकों से परियोजनाओं के लिए सरल विगेट्स विकसित करने में अच्छा समय बिताया है:

var project = project || {};

(function() {

  project.elements = {
    prop1: val1,
    prop2: val2
  }

  project.method1 = function(val) {
    // Do this
  }

  project.method2 = function(val) {
    // Do that
  }

  project.init = function() {
    project.method1(project.elements.prop1)
    project.method2(project.elements.prop2)
  }
})()

project.init();

लेकिन मैंने अपने प्रारूप को निम्न में बदलना शुरू कर दिया है:

function Project() {
  this.elements = {
    prop1: val1,
    prop2: val2
  }

  this.method_one(this.elements.prop1);
  this.method_two(this.elements.prop2);
}

Project.prototype.method_one = function (val) {
  // 
};

Project.prototype.method_two = function (val) {
  //
};

new Project();

दी गई, ये मूर्खतापूर्ण उदाहरण हैं इसलिए न कि एक्सल के चारों ओर लिपटे रहें। लेकिन कार्यात्मक अंतर क्या है और मुझे एक या दूसरे को कब चुनना चाहिए?


मुझे लगता है कि आपका पहला कोड उदाहरण काम नहीं करेगा क्योंकि प्रोजेक्ट गुंजाइश नहीं छोड़ता है। जेएस में विरासत का उपयोग करने के लिए आप प्रोटोटाइप का उपयोग करते हैं। पहला उदाहरण परियोजना का विस्तार करने के लिए नहीं है, इसलिए पुन: प्रयोज्यता सीमित हो सकती है।
ऐच

हाँ, मैंने गलती projectसे फ़ंक्शन के अंदर घोषणा को रखा । अपडेट किया गया।
JDillon522 21

मुझे भी। पहला उदाहरण स्थिर है, दूसरा वस्तु उन्मुख है।
ऐच

1
यदि आप ऑब्जेक्ट के केवल एक उदाहरण का उपयोग कर रहे हैं, तो कोई भी कारण नहीं है जो प्रोटोटाइप परिभाषा का उपयोग करता है। और आपको क्या चाहिए - एक मॉड्यूल प्रारूप है - इसके लिए बहुत सारे विकल्प हैं, देखें: addyosmani.com/writing-modular-js
c69

1
सिंगलटन पैटर्न के लिए पहला एक गैर-सिंगलटन के लिए दूसरा (जब 1 क्लास में कई ऑब्जेक्ट हो सकते हैं)
कोकिज़ू

जवाबों:


6

पहले अंतर को संक्षेप में प्रस्तुत किया जा सकता है: वर्ग thisके उदाहरण को संदर्भित करता है । prototypeको संदर्भित करता है परिभाषा

मान लें कि हमारे पास निम्न वर्ग है:

var Flight = function ( number ) { this.number = number; };

इसलिए यहाँ हम this.numberकक्षा के हर उदाहरण के साथ जुड़ रहे हैं , और यह समझ में आता है क्योंकि प्रत्येक की Flightअपनी उड़ान संख्या होनी चाहिए।

var flightOne = new Flight( "ABC" );
var flightTwo = new Flight( "XYZ" );

इसके विपरीत, prototypeएकल संपत्ति को परिभाषित करता है जिसे सभी उदाहरणों द्वारा पहुँचा जा सकता है।

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

Flight.prototype.getNumber = function () { return this.number; };

दूसरा अंतर उस तरीके के बारे में है जिसे जावास्क्रिप्ट किसी वस्तु की संपत्ति के लिए खोजता है। जब आप खोज रहे हैं Object.whatever, तो जावास्क्रिप्ट सभी तरह से मुख्य ऑब्जेक्ट ऑब्जेक्ट (ऑब्जेक्ट जो कि बाकी सब कुछ विरासत में मिला है) तक जाता है, और जैसे ही यह एक मैच पाता है यह वापस आ जाएगा या इसे कॉल करेगा।

लेकिन यह केवल प्रोटोप्टेड गुणों के लिए होता है। इसलिए यदि आपके पास उच्च स्तर पर कहीं है this.whatever, तो जावास्क्रिप्ट इसे एक मैच के रूप में नहीं मानेगा और खोज जारी रखेगा।

आइए देखें कि यह वास्तविकता में कैसे होता है।

पहले ध्यान दें कि [लगभग] सब कुछ जावास्क्रिप्ट में ऑब्जेक्ट हैं । इसे इस्तेमाल करे:

typeof null

अब देखते हैं कि अंदर क्या है Object(ऊपरवाला नोट Oऔर .अंत में)। Google Chrome के डेवलपर टूल में जब आप प्रवेश करते हैं .तो आपको उस विशिष्ट ऑब्जेक्ट के अंदर उपलब्ध गुणों की एक सूची मिल जाएगी।

Object.

अब के लिए एक ही काम करते हैं Function:

Function.

आप nameविधि नोटिस कर सकते हैं । बस जाओ और आग लगा दो और देखते हैं क्या होता है:

Object.name
Function.name

अब एक फंक्शन बनाते हैं:

var myFunc = function () {};

और देखते हैं कि क्या हमें यहां भी nameविधि मिली है :

myFunc.name

आपको एक खाली स्ट्रिंग मिलना चाहिए, लेकिन यह ठीक है। आपको एक त्रुटि या अपवाद नहीं मिलना चाहिए।

अब उस देवता की तरह कुछ जोड़ते हैं Objectऔर देखते हैं कि क्या हम इसे अन्य स्थानों पर भी प्राप्त करते हैं?

Object.prototype.test = "Okay!";

और वहाँ तुम जाओ:

Object.prototype.test
Function.prototype.test
myFunc.prototype.test

सभी मामलों में आपको देखना चाहिए "Okay!"

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

उस सभी ने कहा, दोनों तरीके सिर्फ भाषा के उपकरण हैं और यह वास्तव में आप पर निर्भर करता है और आप जिस समस्या को हल करने का प्रयास कर रहे हैं वह बेहतर है।

यदि आपको किसी वर्ग के प्रत्येक उदाहरण के लिए प्रासंगिक होना चाहिए, तो उपयोग करें this। यदि आपको प्रत्येक उदाहरण पर समान कार्य करने के लिए एक संपत्ति की आवश्यकता है, तो उपयोग करें prototype

अपडेट करें

आपके नमूना स्निपेट के बारे में, पहला सिंगलटन का एक उदाहरण है , इसलिए यह thisऑब्जेक्ट बॉडी के भीतर उपयोग करने के लिए समझ में आता है । आप इसे इस तरह से मॉड्यूलर बनाकर अपने उदाहरण में सुधार कर सकते हैं (और आपको हमेशा उपयोग करने की आवश्यकता नहीं है this)।

/* Assuming it will run in a web browser */
(function (window) {
    window.myApp = {
        ...
    }
})( window );

/* And in other pages ... */
(function (myApp) {
    myApp.Module = {
        ...
    }
})( myApp );

/* And if you prefer Encapsulation */
(function (myApp) {
    myApp.Module = {
         "foo": "Foo",
         "bar": function ( string ) {
             return string;
         },
         return {
             "foor": foo,
             "bar": bar
         }
    }
})( myApp );

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

अपडेट करें

thisपूर्वता लेने के बारे में विस्तार से prototypeबताने के लिए मैं आपको एक उदाहरण दिखा सकता हूं और आपको बता सकता हूं कि इसे कैसे समझाया जा सकता है, लेकिन मेरे पास इसे वापस करने के लिए कोई बाहरी संसाधन नहीं हैं।

उदाहरण बहुत सरल है:

var myClass = function () { this.foo = "Foo"; };
myClass.prototype.foo = "nice try!";
myClass.prototype.bar = "Bar";

var obj = new myClass;
obj.foo;     // Still contains "Foo" ...
obj.bar;     // Contains "Bar" as expected

स्पष्टीकरण, जैसा कि हम जानते हैं, thisसंदर्भ के लिए प्रासंगिक है। इसलिए यह तब तक अस्तित्व में नहीं आएगा जब तक कि संदर्भ तैयार न हो जाए। जब संदर्भ तैयार है? जब नया उदाहरण बनाया जा रहा है! आपको अब बाकी का अनुमान लगाना चाहिए! इसका मतलब यह है कि भले ही एक prototypeपरिभाषा है, लेकिन thisपूर्वता लेने के लिए और अधिक समझ में आता है क्योंकि यह उस पल में बनाए जा रहे नए उदाहरण के बारे में है।


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

@ JDillon522 खुशी है कि सुनने के लिए। मैं इसे अगले घंटों में अपडेट करने की कोशिश करूंगा!
53777A

@ JDillon522 बस एक त्वरित अद्यतन किया। उम्मीद है कि यह इस बार अधिक स्पष्ट होगा।
53777A

@ JDillon522 अपने सैंपल स्निपेट्स के बारे में थोड़ा और ...
53777A

अच्छा सिंगलटन उदाहरण। इसलिए मैंने thisमूर्खतापूर्ण प्रोटोटाइप उदाहरण में इस्तेमाल किया क्योंकि thisइसके गुणों को संदर्भित करता है, जिसमें इसकी विधियां भी शामिल हैं। मैं कोड के बारे में पढ़ने से सबसे अच्छा नहीं सीखता, लेकिन कोड को देखने से ज्यादा। (उस पर एमडीएन का बिट , ऑब्जेक्ट प्लेग्राउंड (आश्चर्यजनक) , और कुछ अन्य)। क्या आप किसी ऐसी चीज की ओर इशारा कर सकते हैं, जो बताती है कि आपके बारे में " thisप्राथमिकता पर प्राथमिकता " का क्या मतलब है prototype? मैं इसे और देखना चाहता हूं।
JDillon522
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.