Aug
5
JavaScript – Much more than Java’s Mini-Me
Filed Under Computers & Tech, Software Development on August 5, 2006 at 9:01 pm
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:
//create the class function Lamp(initialState){ this.isOn = initialState; this.turnOn = function(){ this.isOn = true; }; this.turnOff = function(){ this.isOn = false; }; this.isOn = function(){ return this.isOn; }; } //use the class var myLamp = new Lamp(true); window.alert(myLamp.isOn()); myLamp.turnOff(); 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:
//create a coloured lamp class function ColouredLamp(initState, initColour){ //first inherit from Lamp this.inheritFrom = Lamp; this.inheritFrom(initState); //then create any extra attributes needed this.colour = initColour; //then create any extra functions needed this.getColour = function(){ return this.colour; }; this.setColour = function(c){ this.colour = c; }; }
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:
//create our PaperIluminWeight class function PaperIluminWeight(initColour, initShape, initWeight){ //inherit from ColouredLamp this.inheritFrom = ColouredLamp; this.inheritFrom(false, initColour); //inherit from PaperWeight this.alsoInheritFrom = PaperWeight; this.alsoInheritFrom(initShape, initWeight); }
Now lets have a look at the inheritance tree for the PaperIluminWeight
class.
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:
public static int sum(int[] nums){ int ans = 0; for(int i=0;i<nums.length;i++){ ans += nums[i]; } return ans; } [/java] <p>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 <code>java.util.LinkedList</code> or a <code>java.util.Vector</code>. 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.</p> <p>Now lets have a look at the right way to implement this in JS:</p>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.
[tags]Java, JavaScript, Programming[/tags]
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
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.
[…] 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. […]