Something that has annoyed me for a long time is that JavaScript is looked on by many people as just being a stripped down version of Java. You take Java, you take out most of the features and you get JS. This is completely wrong. The two are two completely different languages which follow different paradigms. One is Hard Typed and Object Oriented, the Other is Loosely Typed and Object Based. To give you an idea of just how different the languages are I would say that Java is to JavaScript like C/C++ is to Perl. I.e. they are completely different languages in just about every respect but their syntax is superficially similar.

Far from being a stripped down version of Java, JS is in many ways a more powerful language and is certainly more feature-rich. And I’m not talking about little conveniences that make programming a little easier but major features that make some things all but impossible to do with Java but which JS does simply and naturally. In this article I’m going to look at some of these features. While I was writing this article, I came up with many less dramatic advantages which JS has over Java, which just make things easier with JS. Initially I had also included those in this article but they made it too long for the modern attention span. Instead, I’m compiling them into a separate article with the working title Hidden JS which I hope to publish within the next week or so. The inspiration for this article was a post by Joel Spolsky entitled Can your programming language do this? which details one of the advantages JS has over Java.

Functions as Variables

This is the feature Joel discussed in great detail so go read his article, he explains it perfectly so I’m not going to waste my time doing it again (and probably less well!).

Multiple Inheritance

Before I get into the guts of this one it’s probably a good idea to point out that JS does all the regular OO stuff. It lets you create objects to encapsulate data and functions, and does inheritance and polymorphism. Yes, it’s true that it does it in an odd way but it does it all none the less (and no less oddly than Perl). In fact, it does it in multiple ways and the different ways have different advantages and disadvantages.

The way I do OO in JS could best be described as creating classes by writing one function that acts as their constructor. Everything is created within this one function, data structures, functions, and, occasionally, even inner classes. To illuminate this lets have a look at a very simple example, a class to represent a lamp:

  1. //create the class
  2. function Lamp(initialState){
  3.   this.isOn = initialState;
  4.  
  5.   this.turnOn = function(){
  6.     this.isOn = true;
  7.   };
  8.  
  9.   this.turnOff = function(){
  10.     this.isOn = false;
  11.   };
  12.  
  13.   this.isOn = function(){
  14.     return this.isOn;
  15.   };
  16. }
  17.  
  18. //use the class
  19. var myLamp = new Lamp(true);
  20. window.alert(myLamp.isOn());
  21. myLamp.turnOff();
  22. window.alert(myLamp.isOn());

The above code shows how to create a class with one property, isOn, and three functions. What happens is that when you create an object with new a new blank object gets passed to the function after the word new and that function builds up the object by adding properties and functions to it. Given this it is not hard to imagine how one might implement inheritance, call another function on the object you’re instantiating from within your ‘constructor’ function. Somewhat annoyingly you do this in two steps, first you map a pointer to the other constructor as some property of your new object, then you call it on yourself. I think an example may make things a little clearer so below is the code for making a coloured lamp by extending our lamp class from above:

  1. //create a coloured lamp class
  2. function ColouredLamp(initState, initColour){
  3.   //first inherit from Lamp
  4.   this.inheritFrom = Lamp;
  5.   this.inheritFrom(initState);
  6.  
  7.   //then create any extra attributes needed
  8.   this.colour = initColour;
  9.  
  10.   //then create any extra functions needed
  11.   this.getColour = function(){
  12.     return this.colour;
  13.   };
  14.   this.setColour = function(c){
  15.     this.colour = c;
  16.   };
  17. }

Now the thing to note is that there is nothing special about the name I chose for the label for the constructor function we are grabbing from outside (inheritFrom). The line that does the inheriting is really no different to calling any function the object contains on itself. Hence, there is no reason you can’t inherit from more constructors. You can, in fact, inherit from as many as you like.

Let us now imagine that we have created a simple class to represent a paper weight with the properties; weight, and shape. Then, let us imagine that we were mad inventors and we had just invented a combined paperweight and lamp and called it a Paper-Ilumin-Weight and that we wanted a JS object to represent it. We could start from scratch and implement a class with the properties colour, state, weight, and shape. But wait, we already have classes for doing both these things complete with all the functions we need for manipulating them. Hence we can just re-use both classes to create our PaperIluminWeight class like so:

  1. //create our PaperIluminWeight class
  2. function PaperIluminWeight(initColour, initShape, initWeight){
  3.   //inherit from ColouredLamp
  4.   this.inheritFrom = ColouredLamp;
  5.   this.inheritFrom(false, initColour);
  6.  
  7.   //inherit from PaperWeight
  8.   this.alsoInheritFrom = PaperWeight;
  9.   this.alsoInheritFrom(initShape, initWeight);
  10. }

Now lets have a look at the inheritance tree for the PaperIluminWeight class.

Figure 1 - The Inheritance Tree for the class PaperIluminWeight

Can you do this with Java? In a word, no, because Java does not allow multiple inheritance. You can achieve some of this functionality with interfaces but not a lot. In Java you would have to choose one of the two parent classes to inherit from and then re-create the functionality for the other. Because ColouredLamp is more complex (having already inherited from Lamp) lets choose that class to inherit from. If we then want to be able to interact with a PaperIluminWeight object as a Lamp or a Coloured Lamp it will work fine but we won’t be able to interact with it as a PaperWeight. We can make a fudge and re-name our class PaperWeight to PaperWeightImplementation and create an interface called PaperWeight that defines the functions that all Paper Weights should have and then have both PaperWeightImplementation and PaperIluminWeight implement that interface but that only gets us half way there. We can now use PaperIluminWeight objects as Paper Weights within our code but, and this is a hugely important but, we still have to re-implement all the functionality in the PaperWeightImplementation class in PaperIluminWeight class. I.e. copy and paste the whole lot in. Now, you don’t need to be a software engineering guru to see that that is an exceptionally bad thing.

Just as the ability to pass functions as variables results in more code re-use and less code replication, so multiple inheritance in JS does the same. JS lets us re-use code in a situation where Java would have us slavishly re-type the same code again with all the software engineering problems that that brings.

Dynamically Build and Execute Code

Most scripting languages will allow you to build up a string programmaticaly and then execute it as code and grab the result. This is generally done with a method called eval which is exactly how JS does it.

Java does not support this. There is no eval method in Java. If you REALLY need to create Java code on the fly and execute it you can do it in a number of really convoluted ways but for all intents and purposes Java does not support dynamic code generation and execution.

You might wonder why you might want to do that though. So far I have not used it often but I have had to use it. Sometimes I use it for form validation when the form to validate could have a variable number of elements with the same name pattern but this is not a great example because you can also achieve this functionality with DOM objects like document.forms. A better example would be a simple calculator widget where you let users build up a string in a disabled text box by clicking buttons on your onscreen calculator and then simply get the answer by putting the value property of that textbox through eval.

One Function, as many or as Few Arguments as You Like

In JS you can pass as many arguments to a function as you like and that function can then decide what to do with those arguments on the fly. You might wonder what I’m on about so let me give you an example. You have to write a function that takes any number of integers and adds them together. Before we do this in JS lets do it in Java:

  1. public static int sum(int[] nums){
  2.   int ans = 0;
  3.   for(int i=0;i<nums.length;i++){
  4.     ans += nums[i];
  5.   }
  6.   return ans;
  7. }

What you should note is that in Java there is no way to make a function take ‘any number’ of arguments so you have to fudge it. In the above code I fudge it by using a single array argument rather than ‘any number of arguments’. We could also have used some other list structure as the single argument, e.g. a java.util.LinkedList or a java.util.Vector. What wrapper we decide to use is irrelevant, the point is that we have to somehow wrap our variable length list of arguments into a single argument to keep Java happy.

Now lets have a look at the right way to implement this in JS:

  1. function sum(){
  2.   var ans = 0;
  3.   for(var i=0;i<arguments.length;i++){
  4.     ans += arguments[i];
  5.   }
  6.   return ans;
  7. }

The code looks quite similar except for one thing: we have not named any of the arguments for the function, instead we are using an array called arguments. JS, like Perl, stores it’s arguments in an array but lets you name some or all of them for convenience if you want. (unlike Perl JS does let you pass an array literal as a single argument.)

You would be right in saying that there is very little difference between the JS version and the Java version when it comes to writing the function. There is a line-for-line equivalence between the functions. Where the difference becomes obvious is when you go to use your functions as illustrated below.

Java first:

  1. int[] numbers1 = {1, 2, 3, 4};
  2. int ans1 = sum(numbers1);
  3. int numbers2[] = {5, 6, 7, 8};
  4. int ans2 = sum(numbers2);

Now the JS:

  1. var ans1 = sum(1, 2, 3, 4);
  2. var ans2 = sum(5, 6, 7, 8);

You’ll notice that the JS code is much simpler. There is only one step involved, call the function and pass it what you want. The Java code on the other hand needs to prepare the array each time before sending it. Things get even worse if you want to do this kind of thing with Objects rather than literals. Have a look at the nasty Java code below:

  1. Integer numbers1 = new Integer[4];
  2. numbers1[0] = new Integer(1);
  3. numbers1[1] = new Integer(2);
  4. numbers1[2] = new Integer(3);
  5. numbers1[3] = new Integer(4);
  6. Integer sum1 = sum(numbers1);
  7. Integer numbers2 = new Integer[4];
  8. numbers2[0] = new Integer(5);
  9. numbers2[1] = new Integer(6);
  10. numbers2[2] = new Integer(7);
  11. numbers2[3] = new Integer(8);
  12. Integer ans2 = sum(numbers2);

Now the power of this feature of the JS language should be obvious.

More perceptive readers have, at this stage, probably realised that this means that JS does not do function overloading and you would be right. In each scope/namespace there is only one function with a particular name. If you create a second function with the same name but a different argument list it will replace the first one, ignore the second or throw an error depending on your implementation of JS. You are now probably asking yourself, is this a problem? The answer is no it isn’t. You do all the work within one function and if you need to do different things depending on what arguments you got you have a look at what’s in the arguments array and take appropriate action. In fact, function overloading is nothing more than a kludge to allow strongly typed languages like Java to approximate variable length argument lists. In general when two functions overload each other they do the same thing but with different data and you just do some converting/default setting and then pass the data on to the overloaded function that does the actual work. In JS you just write one function that does the work regardless of how you called it. Anything you can do with multiple overloaded functions you can do with one single function in JS and TBH that makes a lot more sense to me, less hoop-jumping and all that.

Edit Classes on the Fly

Although it is easy, in Java, to take the functionality from any System object (like java.lang.String) and add it to an object of your own (you just extend the class), it is not possible to add functionality to the System classes. You can’t, for example, decide that there should be a function in java.lang.Integer to return an Integer which is made up of the digits of the original Integer reversed and add it in to the class (no idea why you’d want to mind!). No prizes for guessing but, in JS you can. You can take any of the classes of object that come with JS and add your own functionality to them.

The reason you can do this is because of the prototype variable that is associated with each object class. When a function is called on an object there are two places that JS looks to find the function to invoke. First it looks to see if the object has a variable of type function with the right name, failing that it looks in the prototype variable for the class that the object belongs to to see if there is a mapping there. We have already seen the former when creating classes in the second section of this article. In the code examples in that section we created the properties and the functions for an object all within the ‘constructor’, adding functions by setting properties of the class equal to function literals. You don’t have to do it that way. You can add the functions in separately at any stage using the prototype variable but this makes things more difficult for inheriting because prototyped functions cannot be inherited simply by calling a constructor function, they have to be explicitly copied to the inheriting class’ prototype variable. This is why I don’t use prototype when creating classes.

Lets now re-visit our sum function form the previous section. Rather than having the function as a standalone function that you then have to pass an array to, it would be much nicer to add the summing functionality straight into JS’s Array class. Below is the code to do just that:

  1. Array.prototype.sum = function(){
  2.   var ans = 0;
  3.   for(var i=0;i<this.length;i++){
  4.     ans += this[i];
  5.   }
  6.   return ans;
  7. }

By inserting the code into the Array class this functionality is now automatically added to all arrays so you can now do things like:

  1. var myArrayOfInts = [1, 2, 3, 4];
  2. window.alert(myArrayOfInts.sum());
  3.  
  4. //because JS is loosly typed even the following will work
  5. //(printing out the Array contents concatonated together)
  6. var mixedArray = ["here", " ", "are", " ", "some", " ", " numbers:", " ", 1, 2, 3, 4];
  7. window.alert(mixedArray.sum());

If you’re already impressed, you’re about to become even more impressed. The more observant among you will have noticed that if you add functions to an object within it’s constructor each object has it’s own copy of the function. This has a downside, it takes up more RAM than the prototyping method, but it makes inheritance easier to implement and it also adds another very interesting ability to the language. In JS it is possible to have two objects of the same type with different implementations of the same function. Take a moment to let that sink in. Without having to create a new class you can make different instances of the same class have different implementations of functions. You just can’t do that in Java. You’d have to have a base class with the default implementation of the function in a parent class (or an abstract function if there is no default) and then a separate subclass overriding the function for each different implementation. If you have a couple of functions that that need a couple of implementations things get very out of hand very very quickly.

That’s great but why on Earth would you want to do that? Well let me give you an example from my everyday life. You want to write a nice object to encapsulate a generic AJAX request because your site uses a lot of AJAX and you’re tired of typing the same code again and again and would like everything to do with a request encapsulated in an object. You start coding this up and it all goes well till you get to your function for handling state changes in the HTTP Request object in which you have to actually DO something with the response you got from the server. Thing is you want to do something different for each instance of your class. In Java this is not possible so you would have to write a base class which implements all the functionality for talking to the server and then make your function to actually do something with the response (lets call it process) abstract. For each different thing you want to do with AJAX you would then have to create a new subclass of your base class and implement process. That is a lot of work for no good reason. In JS you can just create an instance of your AJAX object, plug in a process function of your choice using a function literal and then use your object.

In fact, my partner wrote a little JS class to encapsulate AJAX in JS in this way which will be released as GPL soon. This object gets used something like this:

[JS]
var req1 = new AjaxReq(“POST”, “http://somewhere.ie/something.do”, “var1=val1&var2=val2″);
req1.process = function(req){
document.getElementById(‘myDynamicDiv’).innerHTML = req.responseText();
}
req1.send();

var req2 = new AjaxReq(“POST”, “http://somewhere.ie/something.do”, “var1=val1&var2=val2″);
req2.process = function(res){
window.alert(res.responseText());
}
req2.send();
[/js]

You’ll note that this code is much simpler and neater than having to create a new class each time you want to do something different with the result you get from the server.

Conclusions

This is by no means an exhaustive list of the cool things that JS can do that Java has trouble with or does less well yet it is a substantial list with some very powerful features. Perl can also do just about everything in this article and there are probably other languages that can too but Java, C and C++ are not among those languages.

Something else to note is that the two features that I consider most powerful (Multiple inheritance and the ability to edit classes on the fly) are made possible because JS supports function literals which is what sparked Joel’s article in the first place. The simple act of allowing you to create a function in the same way as a variable and then pass it round as if it was a variable gives JS immense power which Java and it’s ilk just do not have.

JS used to be a language confined to just the HTML page but is is now growing beyond that. JS is used to power FireFox extensions, Mac OS X Dashboard Widgets and Yahoo Desktop Widgets (or what ever Confabulator is now called) as well as other non-web applications. Considering how powerful the language is it seems a shame that most people don’t realise what it can do or that it has now broken free from the HTML page. I have no doubt that we will see JS branch out into even more applications soon and I for one am really looking forward to that.

Technorati Tags: , ,

Comments

3 Responses to “JavaScript – Much more than Java’s Mini-Me”

  1. Des Traynor on August 7th, 2006 8:18 pm

    Good stuff Bart. My last comment dissappeared so this is what I saved from it

    1) Multiple Inheritance is one of those concepts that seems like a great idea, and was heralded as C++s killer feature (back when C++ was the King of OO), but I am still stuck for an example of when it’s actually useful to use Multiple Inhertiance. It always seems to come with incredible complexity, and out of a desire to use Multiple Inheritance, rather than a desire to do the right thing.

    2) You’ve probably read this already, but its good stuff re: Eval http://24ways.org/advent/dont-be-eval

    3) A good guide on the “gotchas” in AJAX, if you’d like one is here…
    http://www.sourcelabs.com/blogs/ajb/2006/04/rocky_shoals_of_ajax_developme.html

  2. Bart B on August 7th, 2006 8:31 pm

    Thanks Des,

    Those two links are handy ones for AJAX heads and the the advice on eval is sound. Just because you can use it does not mean you should. It can be really great (as in the AJAX example) but it should be used with caution.

    As for Multiple Inheritance, my experience has been that in general the real world we are trying to model tends to be hierarchical in a simple way so naturally modeling it will also generally result in simple inheritance trees and hence you don’t need multiple inheritance often but there are good real world applications for it.

    So far I think I’ve used it twice in real world code. Both times for doing very complex wizard interfaces in JS. I’m trying to remember the exact details but it basically involved GUI elements that were a combination of two other GUI elements. I think one of them was a submenu inheriting from menu item and from menu or something like that. Multiple Inheritance is not needed in many situations but when it is needed it saves you from code duplication which is an evil I try to avoid.

  3. Are the Days of JS and AJAX numbered? : Bart Busschots on February 15th, 2007 10:32 pm

    [...] A couple of months back I wrote two articles singing JavaScript’s praises from a programmer’s point of view (JavaScript – Much more than Java’s Mini-Me & Hidden JavaScript). In the last one I hinted that there would be a follow-on article showing a darker side to JS. This is that article, just a few months later than I’d planned. Unlike the previous two articles this one is not really aimed at programmers, it’s aimed at anyone who surfs the web. [...]

Leave a Reply




Before you post a comment please remember that commenting on my blog is a privilege not a right. I won't approve comments that are obscene, offensive or insulting. For more info please read this post.

Subscribe without commenting