2012-06-12 29 views
5

काम नहीं कर रहा है मुझे जावास्क्रिप्ट के साथ कुछ समस्याएं आ रही हैं। मुझे निम्नलिखित कोड मिल गया है:जावास्क्रिप्ट: सरणी में विरासत वर्ग जोड़ना

<html> 
<head> 
<title>Test</title> 
<script type="text/javascript"> 
function Control(){ 
    var name; 

    this.setName = function(newName){ 
     name = newName; 
    }; 

    this.getName = function(){ 
     return name; 
    }; 
} 

function SpecializedControl(){ 
} 
SpecializedControl.prototype = new Control(); 

function Form(){ 
    var formControls = []; 

    this.addControl = function(control){ 
     formControls.push(control); 

     alert(formControls[0].getName()); 
    }; 
} 

var form = new Form(); 

var control1 = new SpecializedControl(); 
control1.setName("Control1"); 
form.addControl(control1); 

var control2 = new SpecializedControl(); 
control2.setName("Control2"); 
form.addControl(control2); 

</script> 
</head> 
<body> 
</body> 
</html> 

नियंत्रण कक्षा से विशेष नियंत्रण प्राप्त होता है।

फॉर्म क्लास में एडकंट्रोल फ़ंक्शन केवल एक सरणी में नियंत्रण जोड़ता है।

समस्या यह है कि जब मैं एक से अधिक स्पेशल कंट्रोल जोड़ता हूं, तो सरणी में मान ओवरड्रिड होते हैं, इसका मतलब है कि जब मैं सरणी में पहले आइटम तक पहुंचता हूं, जो "नियंत्रण 1" होना चाहिए, तो मुझे "नियंत्रण 2" । कंट्रोल 1 अब सरणी में नहीं है।

जब मैं नियंत्रण ऑब्जेक्ट्स के साथ एक ही फ़ंक्शन का उपयोग करता हूं क्योंकि पैरामीटर सब कुछ अपेक्षित काम करता है।

क्या कोई जानता है कि ऐसा क्यों होता है और इसे ठीक करने के लिए क्या किया जा सकता है?

उत्तर

5

सरणी में मानों ओवरराइड नहीं किया जा रहा है ; समस्या यह है कि दोनों नियंत्रण एक ही name चर साझा करते हैं। चूंकि Control फ़ंक्शन केवल एक बार निष्पादित होता है, इसलिए केवल एक name वैरिएबल कभी घोषित किया जाता है।

आपके पास इसे ठीक करने के लिए दो मुख्य विकल्प हैं। (1) name एक इंस्टेंस वैरिएबल बनाएं जो प्रत्येक व्यक्तिगत नियंत्रण के लिए विशिष्ट है (उदा। this._name)। (2) SpecializedControl कन्स्ट्रक्टर के अंदर से Control फ़ंक्शन निष्पादित करें। (असल में, आईएमओ, एक संतुलित और पूर्ण विरासत मॉडल के लिए आपको इन दोनों विधियों में से कुछ करना चाहिए)।

यहां तीन कार्य समाधान हैं। क्रमशः पहले दो उपयोग विकल्प (1) और (2)। तीसरा दोनों तरीकों को जोड़ता है और जिस तरह से मैं इसे करता हूं (लेकिन joi की आवश्यकता है)।

विकल्प 1:

function Control(){ 

    this.setName = function(newName){ 
     this._name = newName; 
    }; 

    this.getName = function(){ 
     return this._name; 
    }; 
} 

विकल्प 2:

function SpecializedControl(){ 
    Control.apply(this, arguments); 
} 

विकल्प 3:

var Control = joi.Unit.sub(function() { 

    function constructor() { 
     this.base(); 
    } 

    constructor.prototype = { 
     '#name': null, 
     setName: function(name) { 
      this['#name'] = name; 
     }, 
     getName: function() { 
      return this['#name']; 
     } 
    }; 

    return constructor; 

}()); 

var SpecializedControl = Control.sub(function() { 

    function constructor() { 
     this.base(); 
    } 

    return constructor; 

}()); 

var Form = joi.Unit.sub(function() { 

    function constructor() { 
     this.base(); 
     this['#formControls'] = []; 
    } 

    constructor.prototype = { 
     '#formControls': null, 
     addControl: function(control) { 
      this['#formControls'].push(control); 
      alert(this['#formControls'][0].getName()); 
     } 
    }; 

    return constructor; 

}()); 

var form = new Form(); 

var control1 = new SpecializedControl(); 
control1.setName("Control1"); 
form.addControl(control1); 

var control2 = new SpecializedControl(); 
control2.setName("Control2"); 
form.addControl(control2);​ 
+1

मैं दूसरे विकल्प की अनुशंसा, उपवर्ग निर्माता में सुपर क्लास के निर्माता बुला। ऐसा करने के लिए सही काम की तरह लगता है। पहले विकल्प को 'name' चर का खुलासा करने की आवश्यकता है और तीसरा विकल्प एक अतिरिक्त लाइब्रेरी का उपयोग करता है जो नियमित वर्ग-आधारित विरासत को जावास्क्रिप्ट के प्रोटोटाइपिकल विरासत के प्रतिस्थापन के रूप में लागू करने का प्रयास करता है। –

+0

जॉय प्रोटोटाइपिकल विरासत का उपयोग करता है, शास्त्रीय विरासत नहीं –

+0

ओह, मेरा बुरा। फिर भी, '# name' केवल सम्मेलन द्वारा आंतरिक है और वास्तव में आपको इसे बाहर से एक्सेस करने से नहीं रोकता है। बंद होने के साथ, आप वास्तव में निजी चर हो सकते हैं। –

5

आपके get/setName फ़ंक्शंस name वैरिएबल के मान को प्राप्त/सेट कर रहे हैं जो Control कन्स्ट्रक्टर फ़ंक्शन के लिए स्थानीय है।

एकमात्र बार जब आपने उस फ़ंक्शन को बुलाया था, तो prototypeSpecializedControl की ऑब्जेक्ट बनाने के लिए एक उदाहरण बनाना था। तो हर बार जब आप उदाहरण से setName का आह्वान करते हैं, तो वह एकल चर अद्यतन किया जा रहा है।

इसलिए get/setName विधियों का संदर्भ देने वाले विधियों के सभी SpecializedControl उदाहरणों की प्रोटोटाइप श्रृंखला में हैं, वे सभी एक ही name देख रहे होंगे।


setName में, आप क्या करना चाहिए ...

this.name = newName; 

और getName में, आपको क्या करना चाहिए ...

return this.name; 
संबंधित मुद्दे