I have built a large application using JavaScript prototype and inheritance. But I am having a hard time organizing my code. For example I have a class carousel which has many functions like this:
Carousel.prototype.next = function () {...}
Carousel.prototype.prev = function () {..}
Carousel.prototype.bindControls = function () {..}
I would like to organize my code like this :
Carousel.prototype.controls = {
next: function () { ... } ,
prev: function() { ... },
bindControls: function () { .. }
}
But this will cause the value of "this" being lost. I can keep track of it using a global instance but this will cause problems when the class is inherited for example In another file I have something like this to override parent class
BigCarousel.prototype.next = function () {...}
My inheritance is done like this:
Function.prototype.inheritsFrom = function (parentClass) {
if (parentClass.constructor === Function) {
//Normal Inheritance
this.prototype = $.extend(this.prototype , new parentClass);
this.prototype.constructor = this;
this.prototype.parent = parentClass.prototype;
}
else {
//Pure Virtual Inheritance
this.prototype = $.extend(this.prototype, parentClass);
this.prototype.constructor = this;
this.prototype.parent = parentClass;
}
return this;
};
So I can do:
BigCarousel.inheritsFrom(Carousel)
Does anyone know how can I work around the "this" value ?
When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property which holds a link to another object called its prototype. That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype.
The most important difference between class- and prototype-based inheritance is that a class defines a type which can be instantiated at runtime, whereas a prototype is itself an object instance.
In JavaScript, an object can inherit properties of another object. The object from where the properties are inherited is called the prototype. In short, objects can inherit properties from other objects — the prototypes.
You could make Controls
a class of it's own:
var Controls = function (controllable_object) {
this.ref = controllable_object;
};
Controls.prototype.next = function () {
this.ref.foo();
}
// ..
var Carousel = function () {
this.controls = new Controls(this);
};
// ..
This doesn't allow you to override the implementation of Controls
though. With more dependency injection you'd get something like:
var Controls = function (controllable_object) {
this.ref = controllable_object;
};
Controls.prototype.next = function () {
this.ref.foo();
}
// ..
var Carousel = function () {
this.controllers = [];
};
Carousel.prototype.addController = function (controller) {
this.controllers.push(controller);
};
// ..
var carousel = new Carousel();
carousel.addController(new Controls(carousel));
My inheritance is done like this:
$.extend(this.prototype , new parentClass);
Ouch. This is not inheritance (with new BigCarousel instanceof Carousel
), but just copying properties. Maybe this is enough for you, but then you should call it mixin. Also, you should avoid using new
for inheritance.
But this will cause the value of "this" being lost. How can I work around that?
It's impossible to have this
point to the parent object with nested properties (as long as you don't want to explicitly set it every time). You have only two choices:
controlNext
, controlBind
, …)Give each of your carousels its own controls
object. For inheritance, make them CarouselControls
instances for example. This especially fits well if those controls are quite independent from the carousel, and don't need to access the carousel they're attached to everywhere. If they are not, you still can pass a reference to the parent carousel into their constructor for example:
this.controls = new CarouselControls(this);
Also, for customizing the controls in different carousels, you might have to subclass the CarouselControls
as well - or you prepare your Controls
object to serve for different carousels in general, so that from BigCarousel
you can
Carousel.call(this); // make this a carousel
this.controls.activate({big: true, fast: false}); // or something
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With