I have a base class that extends a Backbone.View. I want to be able to call the super's 'initialize' after overriding the 'initialize' on a sub class. How can I accomplish calling the super of an extended class in javascript in the most robust and clearest way?
I have seen this (Super in Backbone), is there a clearer way to accomplish this without having to know who the super class is before hand?
App.Views.BaseView = Backbone.View.extend({
initialize: function(templateContext){
this.super_called = true;
}
});
For all of my sub views, I want to take advantage of the already written initialize function.
App.Views.ChildViewWorks = App.Views.extend({});
var newView = new App.Views.ChildViewWorks();
alert(newView.super_called); // print true
App.Views.ChildViewDoesNotWork = App.Views.extend({
initialize: function(templateContext){
this.super_called = false;
//what line of code can I add here to call the super initialize()?
}
});
var newViewWrong = new App.Views.ChildViewDoesNotWork();
alert(newViewWrong.super_called); //now equal to false because I have not called the super.
App.Views.ChildViewDoesNotWork = App.Views.BaseView.extend({
initialize: function(templateContext){
this.super_called = false;
App.Views.BaseView.prototype.initialize.call(this);
}
});
Related
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 ?
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:
Forget it, and organize your methods by prefixing them (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
You can use the .bind method of Function.
In Javascript Functions inherit from Object, so they have their own methods. One of those methods is .bind:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind
Also you are doing inheritance wrong, the right way with raw Javascript is:
ChildClass= function() {
ParentClass.apply(this, arguments); //calling parent constructor
//constructor
};
ChildClass.prototype= new ParentClass();
Then you can simply do this on your constructor:
Courossel= function() {
ParentClass.apply(this, arguments); //calling parent constructor
this.controls.next.bind(this);
this.controls.prev.bind(this);
this.controls.bindControls.bind(this);
}
But I have to say that Frits suggestion is better, make the controls their own class and instantiate it on Carousel constructor passing a reference to your Carousel instance (the this keyword). Just don't call it ".ref", it's confusing.
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 ?
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:
Forget it, and organize your methods by prefixing them (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
You can use the .bind method of Function.
In Javascript Functions inherit from Object, so they have their own methods. One of those methods is .bind:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind
Also you are doing inheritance wrong, the right way with raw Javascript is:
ChildClass= function() {
ParentClass.apply(this, arguments); //calling parent constructor
//constructor
};
ChildClass.prototype= new ParentClass();
Then you can simply do this on your constructor:
Courossel= function() {
ParentClass.apply(this, arguments); //calling parent constructor
this.controls.next.bind(this);
this.controls.prev.bind(this);
this.controls.bindControls.bind(this);
}
But I have to say that Frits suggestion is better, make the controls their own class and instantiate it on Carousel constructor passing a reference to your Carousel instance (the this keyword). Just don't call it ".ref", it's confusing.
Could any one shows an example for creating a class using prototype.js and how it works.Can anyone provide good examples and tutorials for prototype.js other than its official site?
Creating PrototypeJS Classes is very similar to creating classes in normal OOP languages.
First start off by naming your class
var myClass = Class.create({ });
This will create an empty class - now populate it with methods, if you put a method initialize PrototypeJS will fire that as the constructor
var myClass = Class.create(
{
initialize : function()
{
this.options = 0;
}
});
You can setup anything you want in the initialize() method like default values or just initializing the properties of the class. Lets put in some other methods and show how to instantiate the class.
var myClass = Class.create(
{
initialize : function()
{
this.options = 0;
},
testme : function()
{
this.options++;
},
showme : function()
{
alert(this.options);
return this.options;
}
});
var theClass = new myClass();
Lets take it one more step and call other methods within methods and pass options to the constructor.
var myClass = Class.create(
{
initialize : function(option)
{
this.options = (option ? option : 0);
this.testme();
},
testme : function()
{
this.options++;
},
showme : function()
{
alert(this.options);
return this.options;
}
});
var theClass = new myClass(200);
theClass.showme();
//will alert 201 and return 201
This is cool and all - but what about class inheritance? That is a big thing in OOP - lets say we have a separate class that is a child class of myClass. For any method that you are overriding in the child class you can pass a first variable as $super and that will refer to the parent's method of the same name - similar to a scope resolution
var myChildClass = Class.create(myClass,
{
initialize : function($super,option)
{
$super(option);
// the child class needs option's default value at 150 or whatever is
// passed so run the parent initialize first and then redefine the
// option property
this.option = (option ? option : 150);
// you can still run methods in the parent that are not overridden in
// the child
this.testme();
}
});
var child = new myChildClass();
child.showme();
//will alert() 151 and return 151
I hope this is helpful for you.
Here are some more complex real world examples from my github
https://github.com/jwestbrook/Prototype.Growler
https://github.com/jwestbrook/Prototype.Watermark
https://github.com/jwestbrook/bootstrap-prototype
I have a setup of multi level backbone inheritance, but would like to call back of the previous super class. Not sure if is possible.
Scenario:
BasicView -> MediumView -> HardView
Where I would love that when HardView created, it will loops to call previous super class initialize function.
Example is here:
http://jsfiddle.net/mochatony/bwB9W/
There are no implicit references to the superclass in standard JavaScript - you have to explicitly call the supertype's methods
var Basic = Backbone.View.extend({
initialize: function(){
console.log('base');
}
});
var Medium = Basic.extend({
initialize: function() {
console.log(Basic.prototype.initialize.apply(this, arguments));
console.log('medium');
}
});
var Hard = Medium.extend({
initialize:function(){
console.log(Medium.prototype.initialize.apply(this, arguments));
console.log('hard');
}
});
var hard = new Hard();
Basically I want inheritable functions as in
Base = function() { };
Base.prototype.foo = function() {
console.log("base foo");
};
Derived = function() { };
somelib.inherit(Derived, Base);
Derived.prototype.foo = function() {
console.log("derived foo");
}
d = new Derived():
d.foo();
And I want it to print
derived foo
base foo
Yes I know I can explicitly call Base.prototype.foo.call(this); I'm just wondering if there is a pattern for calling overridden super class functions automatically. The problem I'm trying to solve is 2 fold.
derived classes should NOT have to remember to call their parent's method, it just happens automatically.
if 1. can't happen then at least I'd like Derived not to call Base by name since that's brittle. Rather I'd like it call parentclass or something so you don't have to know the base. That way if you change the name of the base you don't have to go fixing every derived class.
You can implement such functionality by using a structure like:
function Base(){}
Base.prototype.destroy = function(){console.log('Base destroy');};
function Derived(){}
Derived.prototype = new Base; // Let Derived inherit from Base
// Override the `destroy` method
Derived.prototype.destroy = function() {
console.log('Derived destroy');
// Call parent class method
this.constructor.prototype.destroy();
// If the context of the method is important, you can use Function.call:
//this.constructor.prototype.destroy.call(this);
};
// Create an instance of Derived, and call the destroy method:
(new Derived).destroy();
I would suggest thinking about exactly why you are doing this, at least in terms of requirement #1. Keep in mind that your desired pattern would take away a great deal of flexibility. For instance, if you have a situation where you want to print the statements in the opposite order:
base foo
derived foo
You would either have to abandon your pattern or create a function foo2() in the derived class which then calls foo() in the base class. Neither is very pretty.
Same goes if you even want to do something as simple as:
derived foo
base foo
one more thing in the derived function
I would contend that using this pattern may work for the exact thing you want to do right now, but may give you fits when you want to make a seemingly trivial change down the road. All to save one line of code!
As far as I know there is no language integrated destructor functionality in JavaScript. It is all about frameworks. If you are using ASP.NET Ajax, for example, the framework would expect that your objects would have a dispose method, responsible for freeing up resources (event handlers). So, it is up to you.
Ok, this isn't quite what you are looking for, in that it's not a "pattern", but it is a potential implementation path you could follow:
Take a look # the MooTools Class.Extras package (for lack of a better word). Using the Chain Class, you could probably get the desired functionality.
var parent = (function () {
var construct = function () {
};
construct.prototype = {
constructor: construct,
destroy: function () {
console.log('parent destruction');
}
}
return construct;
})();
var child = (function (parent) {
var construct = function () {
};
construct.prototype = Object.create(parent.prototype);
construct.prototype.constructor = construct;
construct.prototype.destroy = function () {
parent.prototype.destroy.call(this); // calling parent, too
console.log('child destruction');
};
return construct;
})(parent);
child_instance = new child();
child_instance.destroy();
I would prefer a way where I don't assign Derived = chainify() so that the api would be the same as you had in your question but as of right now this is the best way I can get it to work. It works by replacing each method of the object with a method that calls the replaced method and travels up the parent chain calling their methods along the way.
function chainify() {
return function () {
var property;
for (property in this) {
if (typeof this[property] === "function") {
this[property] = chain(this[property], property);
}
}
function chain(method, method_name) {
return function() {
method();
var current = this;
while (current = current.parent) {
if (current.hasOwnProperty(method_name)) {
current[method_name].apply(this, arguments);
}
}
};
}
}
}
var somelib = function() { };
somelib.inherit = function (derive, base) {
derive.prototype = new base;
derive.prototype.parent = base.prototype;
};
var Base = function() { };
Base.prototype.foo = function() {
console.log("base foo");
};
var Derived = chainify();
somelib.inherit(Derived, Base);
Derived.prototype.foo = function() {
console.log("derived foo");
};
d = new Derived();
d.foo();