Treat JavaScript right!
Written by Ian Elliot   
Wednesday, 09 March 2011
Article Index
Treat JavaScript right!
Inheritance

A radical look at JavaScript that proposes we should play to its strengths and stop trying to make it look like other far less exciting languages!

 

JavaScript is a unique among the current crop of languages.

It has many radical features which, if it had been presented as a new exciting language, would have won it many friends.

Instead it was introduced as a workhorse scripting language that has been misunderstood by many, often inadequate, programmers.

Even the competent programmers who have had the pleasure of getting to know it have usually attempted to reconstruct the image of their favourite language by introducing features like class and inheritance or functional constructs like map and reduce.

When JavaScript was  indeed "just this scripting language" it probably didn't matter but now it is a fast, mainstream, programming language capable of being used for image processing, creating games, 3D graphics, sound and video and so on.... 

JavaScript is a full programming language and it is time to take it seriously and treat it as itself, rather than trying to make it look like some other language.

Objects not classes

The biggest problem with JavaScript according to many experienced programmers is that it lacks class. Of course, the languages that they are experienced in all have class and often take a strongly typed approach to class and objects. Neither concept is necessary nor beneficial to JavaScript.

The key idea is that Javascript has objects - some built in but the majority custom created. You don't first create a class template and then instantiate objects - you simply get on and create objects.

For example:

var myObject={};
myObject.myMethod=function(){};
myObject.myProperty="data";

or you could use an object literal or a new Object declaration as alternatives. The point is that no matter how you create an object you are doing it directly and without the need or use for the idea of a class.

So why do we see so many attempts to re-introduce the idea of class into JavaScript?

There are three main reasons. The first is that a class definition is used to create multiple instances of an object. The second is that class is used to define type and third inheritance is implemented via class.

All three are entirely unnecessary and were introduced to deal with the split between design time and run time present in most of the well known object-oriented languages. With an interpreted language like JavaScript there is no distinction and there is no need to do things in the same way.

In JavaScript objects are created by the execution of the instructions that build the object.

Let's look at how each of the class requirements can be met in an interpreted dynamic language.

When it comes to instantiating multiple objects the first thing to say is that in JavaScript the majority of objects are singletons and there is no requirement to have a mechanism that will instantiate multiple copies.

When you do need multiple copies of an object then the object is often very simple and most like a data structure. In any case the simplest method of creating multiple copies of an object is to use a factory function. Before going on it is worth making the situation clear - in JavaScript functions are objects so it is equally correct to think in terms of factory objects which create other objects but to keep things simple let's work with factory functions.

To create as many copies of an object as you like you simply write a function that creates the object and returns it:

myObjectFactory=function(){
var myTempObject={};
myTempObject.myMethod=function(){
alert(myTempObject.myProperty)};
myTempObject.myProperty="data";
return myTempObject;
}

Now you can "stamp out" as many copies of the object as desire:

var o1=myObjectFactory();
var o2=myObjectFactory();

and so on.

Notice that using a factory function extends the range of possible behaviours an object can have. The whole thing works because of closure - the myTempObject variable is still available to the methods of the object even though it has gone out of scope. It acts like a private variable which references the object i.e. a stand in for "this". The same mechanism can be used to implement additional private variables that can be used for any purpose -simply define them using var and use them in the objects methods.

Notice that there is no notion of static or class variables because there is no need for the idea of class only object.

As a small aside it is worth mentioning that there are many ways of creating a class factory. You can use "this" in place of the private object variable myTempObject in the example or you could go the whole way and write a constructor and use new. What matters at this point is not the exact way you create an object using a function, but the simple fact that you do it without having to invent the concept of class.

Type or the lack of it

So objects are created and constructed as part of code at run time. Now we turn out attention to type. For primitive things like integers, floats and chars type seems like a really good idea because it defined what you can do with them - addition or concatenation. This basic idea of data type is later extended to objects where objects of the same type have the same properties and methods. It is then later extended even further into a type hierarchy where derived type has all of the properties and methods of its parent and some of its own. The point being that you can always treat a derived type as being of its parent type because it has sufficient methods and properties to be used in its place.

Now think about this for a moment. What we are concerned about when we talk of type is what properties and methods an object has. In JavaScript and object can have methods and properties added at run time. What this means is that any attempt to use out of place concepts like type within JavaScript are doomed to failure.

JavaScript is a dynamic language that is so structured that the concept of type is meaningless.

In JavaScript the most you can ask is if an object supports a particular property or method - and surprisingly this is enough.

The sad part is that JavaScript does have a feeble type system grafted onto it in the form of the constructor. When you create an object using the new operator the object has a constructor property and this is used as a stand in for type. The idea is that every object created by the constructor function has the same properties and methods and therefore can be regarded as being of the same type....

Notice the problem. An object that has been created by a constructor i.e. using new, is no different from any other object and can have properties and methods added and deleted. The constructor based concept of type is worthless. True JavaScript cannot sustain a construct of type and you might as well get used to it.


How does this typeless object environment change things?

Surprisingly the answer is not much but it is a big simplification.

Instead of having to worry about object hierarchies, up casting, down casting and so on all you have to worry about is - does it have the method/property I'm about to use.

You can write defensive code that checks that every property or method is present in the object or you can just ensure that it is so by reading the code. This may sound primitive but it is what the compiler does in other languages when it performs type checking. The point is that JavaScript still lacks appropriate tools to make it more difficult to use. A code checker that determined the validity of each type or property access on each object before the code was run would be fairly easy to write. Of course there would be cased where the object used could only be determined at run time and in this case you could have the option of adding a trap for illegal access. 

You don't need a concept of type to ensure that an object has a method or property that you are about to use.

Banner

<ASIN:0596517742>
<ASIN:0596805527>
<ASIN:0470684143>



Last Updated ( Thursday, 10 March 2011 )