Javascript inheritance issue when using prototypes - instances overwritten :(

I am new to JavaScript programming and I have a legacy nightmare. I am writing code for the Appcelerator Titanium and I have a base class called Slide2D that I want to inherit.

So, I put a few functions in the Slide2D prototype. They will usually not be overwritten, but will be called from classes derived from Slide2D. These functions will also be called from other parts of the program. There are also various event handlers used to control animations in Titanium.

If I make a couple of these slides in some calling code (using the new one)

var s = new Slide2D('slide1', 'background1.png', etc...... var t = new Slide2D('slide2', 'background2.png', etc...... 

all of my prototype methods point to the last Slide2D created, regardless of whether I use s or t. Therefore, "slide2" will always be displayed, even if I use the s variable.

It drives me crazy - any help would be greatly appreciated.

Sorry for the length of the code, but here it is:

 function Slide2D(name, backgroundImage, transform, inAnimation, outAnimation) { Titanium.API.info('Slide2D - Constructor - ' + name); var _self = this; var _name = name; var _backgroundImage = backgroundImage; var _startingTransform = transform; var _slideView = Titanium.UI.createView({ backgroundImage: _backgroundImage, transform: transform }); var _animateInAnimation = Titanium.UI.createAnimation(); _animateInAnimation.transform = Titanium.UI.create2DMatrix().translate(0,0); _animateInAnimation.duration = 750; var _animateOutAnimation = Titanium.UI.createAnimation(); _animateOutAnimation.transform = Titanium.UI.create2DMatrix().translate(-1024,0); _animateOutAnimation.duration = 750; var onAnimateInStart = function() { Titanium.API.info('Slide2D.onAnimateInStart'); Titanium.App.fireEvent('animateInStart', {slideName: _name}); _animateInAnimation.removeEventListener('start', onAnimateInStart); }; var onAnimateOutStart = function() { Titanium.API.info('Slide2D.onAnimateOutStart'); Titanium.App.fireEvent('animateOutStart', {slideName: _name}); _animateInAnimation.removeEventListener('start', onAnimateOutStart); }; var onAnimateInComplete = function() { Titanium.API.info('Slide2D.onAnimateInComplete'); Titanium.App.fireEvent('animateInComplete', {slideName: _name}); _animateInAnimation.removeEventListener('complete', onAnimateInComplete); }; var onAnimateOutComplete = function() { Titanium.API.info('Slide2D.onAnimateOutComplete'); Titanium.App.fireEvent('animateOutComplete', {slideName: _name}); _animateOutAnimation.removeEventListener('complete', onAnimateOutComplete); }; _animateInAnimation.addEventListener('start', onAnimateInStart); _animateOutAnimation.addEventListener('start', onAnimateOutStart); _animateInAnimation.addEventListener('complete',onAnimateInComplete); _animateOutAnimation.addEventListener('complete', onAnimateOutComplete); Slide2D.prototype.animateIn = function(){ Titanium.API.info('Slide2D.prototype.animateIn - ' + _name); _slideView.animate(_animateInAnimation); }; Slide2D.prototype.animateOut = function(){ Titanium.API.info('Slide2D.prototype.animateOut'); _slideView.animate(_animateOutAnimation); }; Slide2D.prototype.getName = function() { return _name; }; Slide2D.prototype.getView = function(){ Titanium.API.info('Slide2D.prototype.getView'); return _slideView; }; Slide2D.prototype.getStartingTransform = function(){ return _startingTransform; }; }; 

Edit

Thanks so much for your prompt reply. I made changes that you recommended and that solved this problem.

However, a new problem has appeared.

I need to call Slide2D.prototype.getView from a derived class - ExtendedSlide2D.

However, now I get the following error:

 Result of expression 'Slide2D.prototype.getView()' [undefined] is not an object at ExtendedSlide2D.js at line ....... 

Here I add a button to the base class view object.

I am sure that this error comes down to my inexperience with the language, but, again, any help would be greatly appreciated.

Once again - here is the code for ExtendedSlide2D:

 Titanium.include('Slide2D.js'); function ExtendedSlide2D(name, backgroundImage, transform, inAnimation, outAnimation) { Titanium.API.info('ExtendedSlide2D - Constructor'); this.base = new Slide2D(name, backgroundImage, transform, inAnimation, outAnimation); ExtendedSlide2D.prototype.constructor = ExtendedSlide2D; var button = Titanium.UI.createButton({title: 'AnimateOut', height: 40, width: 200, top: 50 }); button.addEventListener('click', function() { Slide2D.prototype.animateOut(); }); Slide2D.prototype.getView().add(button); } ExtendedSlide2D.prototype = new Slide2D(); 
+6
javascript prototype class prototypal-inheritance appcelerator
source share
1 answer

You will need to transfer the methods that you add to the prototype outside the Slide2D constructor function. Thus, they are defined only once, and not every instance of the object.

And then for those prototype functions for accessing the "internal" ones like _name, _slideView, etc. You will need to convert all your "vars" (currently available at close) to be properties of the object itself. Then reference all of these element properties using "this". Console.

Below, I roughly replaced all your "vars" with this.properties. This conversion requires only the properties and functions necessary to access the prototype. For internal functions (such as your animated functions), they can still use the keys available for closing.

 function Slide2D(name, backgroundImage, transform, inAnimation, outAnimation) { Titanium.API.info('Slide2D - Constructor - ' + name); _self = this; this._name = name; this._backgroundImage = backgroundImage; this._startingTransform = transform; this._slideView = Titanium.UI.createView({ backgroundImage: this._backgroundImage, transform: transform }); this._animateInAnimation = Titanium.UI.createAnimation(); this._animateInAnimation.transform = Titanium.UI.create2DMatrix().translate(0, 0); this._animateInAnimation.duration = 750; /// ... }; Slide2D.prototype.animateIn = function () { Titanium.API.info('Slide2D.prototype.animateIn - ' + this._name); this._slideView.animate(this._animateInAnimation); }; Slide2D.prototype.animateOut = function () { Titanium.API.info('Slide2D.prototype.animateOut'); this._slideView.animate(this._animateOutAnimation); }; Slide2D.prototype.getName = function () { this._name; }; Slide2D.prototype.getView = function () { Titanium.API.info('Slide2D.prototype.getView'); this._slideView; }; Slide2D.prototype.getStartingTransform = function () { this._startingTransform; }; 
+2
source share

All Articles