2009-11-30 14 views
10

मैं जेएस के लिए अपेक्षाकृत नया हूं और मुझे ओओपी सिद्धांतों को सही ढंग से अनुकरण करने में समस्याएं हैं।जावास्क्रिप्ट क्लासेस और वेरिएबल स्कोप

मुझे लगता है कि मेरे पास दो प्रश्न हैं। पहला प्रश्न चर घोषित करने के कई तरीकों से संबंधित है।

function clazz(a) 
{ 
    this.b = 2; 
    var c = 3; 
    this.prototype.d = 4; // or clazz.prototype.d = 4? 
} 

var myClazz = new clazz(1); 

हूँ मैं निम्नलिखित आकलन में सही कर:

एक निजी चर कि उदाहरण के विशिष्ट है (clazz की यानी अलग-अलग विविधताएं अद्वितीय और स्वतंत्र वैरिएबल नहीं होगा

मैं एक वर्ग है कहो 'ए')। इसे क्लैज के भीतर से एक्सेस किया जा सकता है: 'ए'।

बी एक सार्वजनिक चर है जो उदाहरण विशिष्ट है। इसे क्लैज़ के भीतर 'this.b' और बाहरी क्लैज से 'myClazz.b' के रूप में एक्सेस किया जा सकता है।

सी एक निजी चर है जो स्थैतिक या वर्ग विशिष्ट है (यानी क्लैज के विभिन्न उदाहरण समान 'सी' चर साझा करेंगे)। इसे क्लैज के किसी भी उदाहरण के भीतर से 'सी' के रूप में एक्सेस किया जा सकता है और क्लैज के उदाहरण में परिवर्तन क्लैज के सभी उदाहरणों में दिखाई देता है।

डी एक सार्वजनिक चर है जो स्थैतिक/वर्ग विशिष्ट है। इसे 'clazz.prototype.d' या 'myClazz.prototype.d' के माध्यम से कहीं से भी एक्सेस किया जा सकता है।

परिवर्तनीय योजना की मेरी समझ के साथ मेरे पास समग्र समस्या यह है कि एक निजी चर घोषित करने का कोई तरीका नहीं है जो स्थैतिक नहीं है (यानी वर्ग के प्रत्येक उदाहरण के लिए एक अद्वितीय संस्करण)।

दूसरा प्रश्न विभिन्न प्रकार की कक्षा घोषणाओं के संबंध में है।

मैं उपयोग कर रहे हैं:

var MySingleton = new function() {...}; 

एकमात्र बनाने के लिए। क्या ये सही है?

var MySingleton = new function() {...}(); 

मैं करने के लिए इस पद्धति का उपयोग कर रहा है: मैं भी इस स्थिति में 'नई' कीवर्ड के प्रभाव के रूप में अनिश्चित के साथ ही जोड़कर() फ़ंक्शन घोषणा के अंत के रूप में इतना करने के लिए कर रहा हूँ धनुकोष्ठक एक कक्षा घोषित करें और फिर उस वर्ग के तत्काल उदाहरण:

function myClass() {...}; 
var classA = new myClass(); 
var classB = new myClass(); 

क्या यह उचित तरीका है?

उत्तर

18

आप a और b के लिए सही कर रहे हैं:

a एक तर्क, केवल constructor function के दायरे के भीतर उपलब्ध है।

b एक सार्वजनिक इंस्टेंस वैरिएबल है, जो उस कन्स्ट्रक्टर फ़ंक्शन के साथ बनाए गए सभी उदाहरणों पर उपलब्ध है।

c एक निजी चर है, जो केवल निर्माता कार्य के भीतर सुलभ है।

d घोषणा अवैध है, क्योंकि prototype वस्तु केवल constructor functions पर इस्तेमाल किया जा करने के लिए है, Clazz.prototype.d = 3; की तरह, यदि आप इसे इस तरह करते हैं, चर साझा किया जाएगा, लेकिन आप एक विशिष्ट उदाहरण पर एक मूल्य प्रदान कर सकते हैं, और डिफ़ॉल्ट मान छायांकित (प्रोटोटाइप श्रृंखला के माध्यम से) होगा।

के लिए "निजी चर" यदि आप उदाहरण के लिए, जिस तरह से आप की घोषणा c उपयोग कर सकते हैं:

function Clazz(){ 
    var c = 3; // private variable 

    this.privilegedMethod = function() { 
     alert(c); 
    }; 
} 

विशेषाधिकृत तरीकों, सार्वजनिक हैं, लेकिन वे "निजी" चर निर्माता समारोह के अंदर घोषित पहुँच सकते हैं।

एकमात्र बनाने के लिए, सबसे आसान तरीका हो सकता है है की तरह शाब्दिक किसी चीज़ का इस्तेमाल करने के लिए,:

var myInstance = { 
    method1: function() { 
    // ... 
    }, 
    method2: function() { 
    // ... 
    } 
}; 

और अगर आप अपने सिंगलटन उदाहरण पर निजी सदस्यों चाहते हैं, आप कर सकते हैं:

var myInstance = (function() { 
    var privateVar = ''; 

    function privateMethod() { 
    // ... 
    } 

    return { // public interface 
    publicMethod1: function() { 
     // all private members are accesible here 
    }, 
    publicMethod2: function() { 
    } 
    }; 
})(); 

यह मॉड्यूल पैटर्न कहा जाता है, यह मूल रूप से closures के उपयोग का लाभ उठाकर, किसी ऑब्जेक्ट पर निजी सदस्यों को समाहित करने की अनुमति देता है।

और जानकारी:

संपादित करें: वाक्य रचना आप पोस्ट के बारे में:

var mySingleton = new (function() { 
    // ... 
})(); 

new ऑपरेटर का उपयोग करके आप दिसम्बर हैं में एक चरण एक "अज्ञात कन्स्ट्रक्टर फ़ंक्शन", जो एक नया ऑब्जेक्ट उदाहरण उत्पन्न करेगा, यह मान्य है लेकिन मैं व्यक्तिगत रूप से "मॉड्यूल" पैटर्न दृष्टिकोण पसंद करूंगा, अपना ऑब्जेक्ट उदाहरण बनाने के लिए (और new से बचें)।

इसके अलावा, new function() {} पढ़ना, मुझे लगता है कि वास्तव में सहज नहीं है और अगर आप अच्छी तरह से समझ नहीं पाते हैं कि new ऑपरेटर कैसे काम करता है तो भ्रम पैदा कर सकता है। यदि आप उन्हें न जोड़ें

कोष्ठकों के बारे में, वे वैकल्पिक हैं, new ऑपरेटर पैरामीटर के बिना समारोह निर्माता कॉल करेंगे (ECMA-262, 11.2.2 देखें)।

+2

+1। एक बहुत ही पूर्ण और सूचनात्मक उत्तर। –

+0

सूचनात्मक उत्तर के लिए धन्यवाद। एक अनुवर्ती: सिंगलटन घोषणा के लिए मॉड्यूल दृष्टिकोण और मूल पोस्ट में संदर्भित शैली के बीच वास्तविक अंतर क्या हैं? – Cmc

+0

** @ लियोर: ** धन्यवाद !, ** सीएमसी: ** मैंने आपके द्वारा पोस्ट किए गए वाक्यविन्यास के बारे में कुछ लिखा है ... – CMS

3

ठीक है, की सुविधा देता है इस पर जाने के:

  1. 'एक' एक तर्क अपने वर्ग के निर्माता को पारित कर दिया है। यह केवल कन्स्ट्रक्टर के आमंत्रण की अवधि के लिए ही मौजूद होगा। इसका मतलब है कि आपको शायद अपना मूल्य कहीं भी स्टोर करना चाहिए।

  2. 'बी' एक सार्वजनिक उदाहरण सदस्य है। यह उदाहरण विशिष्ट है (हालांकि, चूंकि आप कन्स्ट्रक्टर में मान निर्दिष्ट कर रहे हैं, इसलिए सभी मामलों में प्रारंभ में 'बी' के लिए समान मूल्य होगा)।

  3. 'सी' एक निजी उदाहरण सदस्य है। हालांकि, यह केवल आपके कन्स्ट्रक्टर के अंदर ही पहुंच योग्य होगा क्योंकि इसे केवल उस दायरे में परिभाषित किया गया है। जब तक आप इसे अपने कन्स्ट्रक्टर फ़ंक्शन के अंदर बंद होने से संदर्भित न करें, तब तक इसका भाग्य ऊपर 'ए' के ​​समान होगा।

  4. 'डी' एक सार्वजनिक उदाहरण सदस्य है। आपकी कक्षा के प्रत्येक उदाहरण में शुरुआत में मूल्य 4 के साथ सदस्य 'डी' होगा। ध्यान दें कि आपकी कक्षा के प्रोटोटाइप सदस्य (जैसे 'डी') के लिए संदर्भ प्रकार ऑब्जेक्ट असाइन करना प्रत्येक इंस्टेंस सदस्य 'डी' को उसी ऑब्जेक्ट को संदर्भित करेगा। उदाहरण:

    MyClass.prototype.d = { prop1: 'val1', prop2: 'val2' };   
    var a = new MyClass(); 
    var b = new MyClass();   
    a.d.prop1 = 'foo'; // is the same as: b.d.prop1 = 'foo'; 
    
  5. वर्ग की स्टेटिक सदस्यों का उपयोग कर परिभाषित कर रहे हैं:

    function MyClass() 
    { 
        // ... 
    }  
    MyClass.staticMemeber = 'I am a static member'; 
    

    आप शायद एक जगह अपने स्थिर सदस्यों/एक वर्गों के लिए सौंपा methods.Everything धारण करने के लिए के रूप में MyClass.prototype का इलाज नहीं करना चाहिए 'प्रोटोटाइप बदले में इसके प्रत्येक उदाहरण का सदस्य है।

  6. जब() फ़ंक्शन परिभाषा (ब्लॉक के ठीक बाद) से जुड़े होते हैं, तो फ़ंक्शन निष्पादित किया जाता है। इसका अर्थ है:

    var myFunc = function() { alert('blah'); }(); 
    

    परिणामस्वरूप एक विधि आमंत्रण से अधिक कुछ नहीं होगा। निम्नलिखित कोड:

    var MySingleton = new function() {...}(); 
    

    मतलब 'MySingleton के लिए निर्माता के रूप में कार्य से वापसी मान() का उपयोग' होगा।

संबंधित मुद्दे