Javascript Inheritance

Before I started working on Squad, most of my experience with object oriented programming came from C++, Java and .Net classes in school, all of which use traditional, class-based OOP. Upon joining Code Together, I was dropped into an existing code base written by programmers who were more experienced at this kind of thing than I was. I was skilled in PHP and jQuery, but had little experience with object oriented PHP and almost no experience with vanilla Javascript.

As you may know, PHP’s object oriented features are, like C++ and Java, class-based. You define classes with properties and methods, extend those classes to make new classes, and create objects which are instances of those classes. Adjusting to OOP PHP in the Zend Framework took a little time, but was fairly straight forward.

Adjusting to more advanced Javascript was more challenging because it is prototype-based and does not use classes, with which I was familiar. After a while, I did become more comfortable with javascript and prototypes and have used it to great success.

One of the main concepts I struggle with is inheritance in prototype-based OOP. A lot of the web references on Google and Bing on the topic try to come up with neat solutions for forcing javascript to use faux classes. Those solutions work, but they don’t really help to solidify straight prototype-based inheritance in my mind. Additionally, most solutions are relatively heavy and much more complex than what I need.

After a lot of trial and error, I came up with the following solution. I know it’s probably not the best way to define objects in Javascript, but it’s based on the coding style of the guys who worked on Squad before me, which is where I learned about prototypal OOP in the first place.

The magic happens with the following 2 lines of code which are inserted at the top of the child object’s constructor.

this._parent=new ParentObject();
for(var i in this._parent)if(!this[i]&&i!="_parent")this[i]=this._parent[i];

It basically creates a new parent object, then copies all of the parent object’s member functions and properties to the child object. It’s not strictly prototypal inheritance, but it does what I need it to do in my simple implementations. What follows is an example using your traditional animal metaphor:

//Parent object
Animal = function(){
this.weight = 100;
this.height = 15;
this.sound = "an Unknown Sound";
this.stride = 1;
};
Animal.prototype = {
move : function(distance){
alert("This animal moved "+(this.stride * distance)+" feet");
},
speak : function(){
alert("This animal says "+this.sound);
}
};

Monkey = function(){
//create a new instance of the parent object -- Animal
this._parent=new Animal();
//Copy all functions and properties from the new _parent object to the Monkey object
for(var i in this._parent)if(!this[i]&&i!="_parent")this[i]=this._parent[i];

this.sound = "Eek eek";
};
Monkey.prototype = {
climb : function(){
alert("The monkey climbed a tree.");
},
move : function()
{
alert("The monkey jumped to a different branch.");
}
};

var someAnimal = new Animal();
someAnimal.speak(); //Alerts "This animal says an Unknown Sound"
someAnimal.move(12); //Alerts "This animal moved 12 feet"
alert(someAnimal.weight); //Alerts "100"

var bobo = new Monkey();
bobo.speak(); //Alerts "This animal says Eek eek"
bobo.move(12); //Alerts "The monkey jumped to a different branch."
bobo.climb(); //Alerts "The monkey climbed a tree."
alert(bobo.weight); //Alerts "100"

Caveats:

While this method mimics inheritence, it doesn’t actually copy the prototype from the parent object to the child object. It only copies the functions and properties. In my case, this is usually all I need it to do. It essentially “fills in the blanks” of the child object using whatever is in the parent object. Also note that changing a property’s value in the child instance will not change it in the parent’s instance:

bobo.weight = 200;
alert(bobo.weight); //200
alert(bobo._parent.weight); //100

The same is true within the context of a member function:

Monkey.prototype.changeWeight = function(weight){
this.weight = weight;
}
...
bobo.changeWeight(200);
alert(bobo.weight); //200
alert(bobo._parent.weight); //100

In the vast majority of cases, you won’t need to access the _parent property. Any functions copied from the parent to the child will automatically gain the context of the child. In our example, the `this` in the speak function becomes bobo automatically, even though the function has been copied from Animal. If you did, however, want to call the parent’s version of a function within an overwritten function, you’d need to change context with something like call() or apply(). Without apply:

Monkey.prototype.move = function(distance){
alert("The monkey jumped to a different branch!");
this._parent.move(distance);
}
...
bobo.stride = 3;
bobo.move(12); //Alerts "The monkey jumped to a different branch!" then also alerts "This animal moved 12 feet"

Then with apply:

Monkey.prototype.move = function(distance){
alert("The monkey jumped to a different branch!");
this._parent.move.apply(this, arguments);
}
...
bobo.stride = 3;
bobo.move(12); //Alerts "The monkey jumped to a different branch!" then also alerts "This animal moved 36 feet"

Note that without apply, the animal moves only 12 feet because the _parent’s stride is still only 1, even though we changed bobo’s stride to 3. With apply, however, the animal moves 36 feet because the function is using bobo’s stride length of 3 instead of _parent’s.
The last problem I’ve come across deals with binding events and has to do with context, much like the last issue. Sometimes I’ll have a dynamically created DOM Element as a property of my object. If I bind an event listener to that object in the parent, the child object’s version will also have that listener, except the context of that function will be the _parent, even though the element is in the child. The following example uses jquery for event binding

Parent = function(){
this.button = document.createElement("button");
this.message = "I am the parent";
$(this.button).click(function(){ alert(this.message)});
}

Child = function(){
this._parent=new Parent();
for(var i in this._parent)if(!this[i]&&i!="_parent")this[i]=this._parent[i];

this.message = "I am the child";
}

childObject = new Child();
$(child.button).click(); //alerts "I am the parent";

I haven’t found a good solution for this problem yet. My workaround in the one case I’ve had this problem is to set a flag that tells the parent not to bind the event if it’s being extended:

Parent = function(inherits){
this.button = document.createElement("button");
this.message = "I am the parent";
if(!inherits)
$(this.button).click(function(){ alert(this.message)});
}

Child = function(){
this._parent=new Parent(true);
for(var i in this._parent)if(!this[i]&&i!="_parent")this[i]=this._parent[i];

this.message = "I am the child";
$(this.button).click(function(){ alert(this.message)});
}

childObject = new Child();
$(child.button).click(); //alerts "I am the child";

Not the most elegant of solutions, but it works.

Conclusion:
This method works great for me. It’s relatively simple and light weight. Depending on your application, you might want a more substantial solution, or better yet, learn how inheritance actually works in Javascript.

TinyMCE and cursor position

Our latest product, Treaty, is built around the web-based rich text editor TinyMCE.  We chose TinyMCE as the editor because it seemed to have the most robust API.

Due to the nature of the product, one main function we needed was the ability to set the position of the caret or cursor in the editor.  Unfortunately, there is no easily accessible method of setting or getting the position of the cursor.  After countless hours of researching on the web and combing through the documentation, I was unable to find a suitable, reliable, cross browser method. Continue reading