Object Oriented Javascript 1: Inheritance

>> Monday, April 9, 2012

Pretty Javascript!

Javascript is such a different language, I wouldn't call it hard to use or understand, but we are used to different and more structured languages, Javascript gives you so much freedom, you end up doing whatever you want, and not quite understanding what's really going on, personally I find this frustrating, as I really want to understand everything I do, afters years of barely using Javascript for web development, for several reasons I decided to go a bit deeper on this, and find out what's really going on with my code.

When we think about object orientation we normally think of languages like Java, or Ruby, in which a Class defines how an object will behave, and you can then implement inheritance by just adding a "extends" to that class definition.
This implementation of Object Orientation is based on classes, Javascript on the other hand uses Prototypes.

Before Prototypes... Let's talk about the new keyword

Hey hey, stop right there my fellow reader, let's take a moment to relax and go back to the basics, let's talk about the new keyword.
In Java, for example, the new keyword takes a class, and creates/instantiates an object based on that class, the object has all the definitions the class specified.
But in Javascript, we have no classes! What on earth does the new keyword do then?
Well the new keyword can only be used on function definitions, and that function will act as a constructor for our new object.

But there are other ways of creating objects, why bother using new? Well let's see! Let's make some objects

var a = {x:12};
var b = {x:12};

As you can see, we have two objects, a and b, they both hold the same definition, but its repeated, what if we wanted to create 10, or 100 objects? Well we use the new keyword! That way all our instances references only one object

var a = function() { this.x = 12; }
var obj = new Array();
for(var i = 0; i < 100; i++) { obj[i] = new a(); }
We just made 100 objects! Inside an array but...well you get the idea, using the new keyword is closely related to classes, as it's how we say "Take this class, make an object modeled after this class", but as we have no class, we just give the new keyword a constructor, and say "Here, make an object and call this constructor".
Inside the constructor, we can use the "this" keyword as if we are already inside our object, just like a regular constructor.

Ok, so we have the equivalent of a class constructor, but how do we set the attributes, and methods to share across all objects? Prototypes!

What are prototypes?

Awesome question! Prototypes are objects, the special thing about prototypes is that every object in Javascript has a prototype (except some system objects), and a prototype specifies the methods and properties the object will have when instantiated.

Let's take a look at this simple code.
var A = function() { this.x = 12; } // function expression
var objA = new A();                    // creates an instance of A, using the A as constructor
> 12
var objB = new A();
> 12
That's nice, we have two instances of A, an anonymous function acts as constructor, and we didn't use prototypes! Using the new keyword, we even create instances properly so the function is referenced and not copied twice. This is a pretty efficient way of defining objects in Javascript.

But why, oh why prototypes then?

I didn't need them before, why learn about them? Well, what if we need to extend our A pseudo-class? As we don't have classes, we have to put all the things we want our instances to share in the prototype, instead of the class! So to inherit something, we use... that's right, the prototype.

Let's first understand how this is possible: When a method of an object is requested, the Javascript interpreter asks the object for that method, if it can't find it, it asks the object for it's prototype, and it seeks the method in the prototype, that way, we can create a chaining of prototypes, and implement inheritance cleanly.

Don't worry! Here is the example
var Animal = function() { this.type = "Mammal"; } var Cat = function() { this.name = "Cat"; } Cat.prototype = new Animal(); // Cat gets all the properties of this object
var myCat = new Cat();
> "Mammal"
> "Cat"
Note that we use new Animal() to set as the prototype, as we need an object, not a function, otherwise it would not work!

As myCat doesn't have a type property, it looks up on the prototype definition of Cat, and calls the method we want, there it is! Inheritance!

Okay so maybe we need prototypes...

Good! Now that I convinced you that prototypes are what cool kids use, let's now take a closer look on protoypes
var A = function(){} // object definition with empty constructor
A.prototype.x = 12; // using the prototype, we define x as 12
var objA = new A(); // create an instance of the object
A.prototype.x = 6; // modify the prototype after instantiating an object
objA.x 6 // ta-da!
Crazy huh? Well maybe it's not that impressive, as you could say "Hey but why don't just change the x property of objA to 6?" Well yes, it would do the same, but imagine x is a function, and there are 10 instances of A, some by inheritance, some regular instances, and we change x, do to something completely different, changing a method at runtime! It's a lot of power! This is why Javascript is so dynamic, and scary sometimes, you have so much freedom! You can have some crazy design patterns for your programs!
As the instances of A don't have an x property, Javascript looks for the prototype's implementation of x, making this possible.

Note: As Javascript is so dynamic you should be careful with your code! Make sure you follow good standards to not end up with a crazy monster of a program, you can't even understand or debug!

Other cool things you can do...

Have you heard of Partial Classes? Not a big deal really, it lets you define a class in separate files, so you have a part of the definition in one, and a part in other, it's not quite the same as inheritance, it's the same class, the compiler just joins all the files and then compiles the class as one.
This is cool, and you can do it in Javascript! This lets you extend classes without inheriting, and making your own extensions, for example, say you want to add a method to Javascript's native String class, it's easy!
String.prototype.isNullorEmpty = function() { return (this == null || this == "" || this == undefined); }
> true
> false
Prototypes are pretty hard to get used to, but they certainly do not lack power!

Post a Comment

  © Blogger template Simple n' Sweet by Ourblogtemplates.com 2009

Back to TOP