2012-09-28 17 views
11

ध्यान में रखते हुए ऑब्जेक्ट निर्माण पैटर्न, एक तरह से करने के लिए है: इस के साथपुन: प्रयोज्य विधियों और निजी गुणों के साथ जावास्क्रिप्ट ऑब्जेक्ट निर्माण पैटर्न कैसे करें? निजी संपत्तियों के साथ

function MyStack(){ 
    var list = [], 
     index = 0; 

    this.push = function(val){ 
     return list[index++] = val; 
    }; 
    this.pop = function(){// ...} 
} 

var stack1 = new MyStack();  stack1.push(5); 
var stack2 = new MyStack();  stack2.push(11); 

समस्या: ढेर के हर उदाहरण यह तरीकों 'पुश' और 'पॉप' की स्वयं की प्रतिलिपि है है।

निर्माता विधि को लागू करने के लिए एक और तरीका है:

function MyStack(){ 
    this.list = []; 
    this.index = 0; 
} 
MyStack.prototype = { 
    insert: function(val){ 
      return this.list[this.index++] = val; 
     }, 
    pop:function(){//...} 
} 

समस्या यहाँ: हम सूची और सूचकांक की गोपनीयता खो देते हैं।

क्या कोई तरीका है, जैसे कि हम दोनों विधियों को गुणों और संपत्तियों की गोपनीयता के बीच पुन: उपयोग कर सकते हैं?

मैं समझता हूं कि हम उन तरीकों के लिए यह कर सकते हैं जो वस्तु के किसी भी राज्य पर काम नहीं करते हैं, लेकिन मैं उन तरीकों के बारे में और बात कर रहा हूं जो राज्य पर काम करते हैं।

+0

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

+0

@ फ़ेलिक्सक्लिंग इसलिए मान लें कि हमारे पास एक सहायक डीएस है, जैसे {id1: {list: [3,4], currentIndex: 2}, id2: {list: [2,1,4], currentIndex: 3}} .. फिर भी MyStack.prototype.insert = function (val) {currState = this.auxiliaryDS [this.id] में; this.currState.list.push (वैल) .. फिर, यह वास्तव में निजी नहीं है। – sbr

+1

आप फ़ंक्शन के अंदर डेटा स्टोर और कन्स्ट्रक्टर फ़ंक्शन को परिभाषित कर सकते हैं और केवल कन्स्ट्रक्टर फ़ंक्शन का पर्दाफाश कर सकते हैं।डेटा स्टोर तब निजी होगा और बाहर से उपलब्ध नहीं होगा। हां, आईडी पहुंच योग्य होगी, लेकिन अगर आप इसे खराब करना चाहते हैं तो आप इसके लिए एक यादृच्छिक संपत्ति नाम भी उत्पन्न कर सकते हैं। जैसा कि मैंने कहा, जेएस इसके लिए नहीं बनाया गया है और आप जो कुछ भी करते हैं वह हैकी और/या जटिल होगा। उचित दस्तावेज आईएमओ अधिक मूल्यवान है। आप यहां कुछ संबंधित प्रश्न यहां देख सकते हैं: http://stackoverflow.com/search?q=javascript+private+instance+variables+and+prototype+methods –

उत्तर

1

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

function MyStack(){ 
    var list = []; 
    var index = 0; 

    this.getIndex = function(){ 
     return index; 
    } 
    this.setIndex = function(val){ 
     index = val; 
    } 
    this.list = function(val){ 
     if(val){ 
      // setter if a value was provided. Illustrating how you can control 
      // index, which I assume is the point of having these things private 
      // to begin with 
      return list[this.setIndex(this.getIndex() + 1)] = val; 
     } 

     // always return list - acts like a getter 
     return list; 
    } 
} 
MyStack.prototype = { 
    insert: function(val){ 
      return this.list(val); 
     }, 
    pop:function(){} 
} 

var stack1 = new MyStack();  
stack1.insert(5); 
var stack2 = new MyStack();  
stack2.insert(11); 
0

मुझे लगता है कि आपके द्वारा वर्णित दोनों दृष्टिकोणों में, जब कभी भी कन्स्ट्रक्टर पैटर्न का उपयोग करके ऑब्जेक्ट बनाया जाता है तो गुणों को इसकी ऑब्जेक्ट्स में कॉपी किया जाएगा। आपने चिंता के रूप में पहले दृष्टिकोण के लिए उल्लेख किया है। मुझे लगता है कि इस दृष्टिकोण में आपकी चिंता के साथ-साथ दूसरे दृष्टिकोण के लिए भी लागू किया जाएगा।

हम आम तौर पर आपके द्वारा वर्णित दूसरे दृष्टिकोण पर जाते हैं जब भी हम किसी अन्य वर्ग में "माइस्टैक" के गुणों का विस्तार करना चाहते हैं।

चलें कहना मैं की तरह

नीचे
var dummy = function(); 
dummy.prototype = MyStack.prototype; 
var MyTest = function(){ 
}; 
MyTest.prototype = new dummy(); // Assigning MyStack properties to MyTest 
var obj = new MyTest(); 
1

आप जॉन Resig के Simple Javascript Inheritance की जांच करनी चाहिए MyTest करने के लिए अपने वर्ग MyStack का विस्तार करना चाहते हैं। यह एक महान पढ़ा गया है, और इसे निजीकरण के लिए समर्थन प्रदान करने के लिए बढ़ा दिया गया है, जिसे Privates.js कहा जाता है;

+0

को Privates.js के बारे में पता नहीं था। – sbr

1

एक कन्स्ट्रक्टर फ़ंक्शन किसी ऑब्जेक्ट को वापस कर सकता है (आवश्यक नहीं यह)। कोई एक कन्स्ट्रक्टर फ़ंक्शन बना सकता है, जो प्रॉक्सी ऑब्जेक्ट देता है, जिसमें "असली" इंस्टेंस ऑब्जेक्ट की "वास्तविक" विधियों के लिए प्रॉक्सी विधियां होती हैं। यह जटिल लग सकता है, लेकिन यह नहीं है; यहाँ एक कोड का टुकड़ा है:

var MyClass = function() { 
    var instanceObj = this; 
    var proxyObj = { 
     myPublicMethod: function() { 
      return instanceObj.myPublicMethod.apply(instanceObj, arguments); 
     } 
    } 
    return proxyObj; 
}; 
MyClass.prototype = { 
    _myPrivateMethod: function() { 
     ... 
    }, 
    myPublicMethod: function() { 
     ... 
    } 
}; 

अच्छी बात यह है कि प्रॉक्सी निर्माण, स्वचालित किया जा सकता है अगर हम संरक्षित तरीकों के नामकरण के लिए एक सम्मेलन को परिभाषित है। मैंने एक छोटी लाइब्रेरी बनाई जो वास्तव में यह करता है: http://idya.github.com/oolib/

+0

यह मेरे लिए अविश्वसनीय रूप से अजीब लग रहा है - क्या आप इसे थोड़ा और समझा सकते हैं? मैंने आपके lib दस्तावेज़ों के माध्यम से इसे पढ़ने की कोशिश की है, लेकिन मैं बिल्कुल नहीं देख रहा हूं कि proxyObj ऑब्जेक्ट क्या कर रहा है – netpoetica

+0

आप MyClass = new MyClass(); 'के साथ MyClass को तुरंत चालू कर सकते हैं। myObj proxyObj होगा: इसमें केवल 1 सदस्य होगा, जिसे MyPublicMethod कहा जाता है। क्या यह समझ में आता है, या आपके पास और सवाल है? मैं खुशी से मदद करता हूँ। – slobo