JavaScript's Rough Childhood

As some of you may know, I'm a fan of JavaScript. Pretty much all of my projects are web apps, and as such, JavaScript is an important part of them.

JavaScript does have its good parts. Parts which at the very least are en par with other languages. It does, however, also have quite a bit of bad parts.

In the beginning, there was Brendan Eich. Eich got hired by Netscape to design a programming language for their web browser. At first, what he had in mind was something resembling Scheme, a dialect of Lisp.

When he had worked for some time on this Scheme-esque language, someone, presumably in Netscape's management, decided they wanted something else. Eich got told to start from scratch. This whole Java-thing seemed to be taking off, so he would have to make it more like Java. "And by the way, we need it in ten days", they told him.

Now, ten days is orders of magnitude less than you need to design a great language. Eich did a great job, but as you would expect however, it did have quite a few unforeseen quirks.

Unsurprisingly, Microsoft decided to copy Netscape. They had a team dedicated to find JavaScript's quirks and replicate them.

Fast forward a bit, and Netscape submit their language to European Computer Manufacturers Association, or ECMA, to make it a standard. ECMA agrees, on the premise that it won't be called JavaScript anymore. A team of people started writing detailed documentation for what was internally called ECMAScript. Microsoft had a key role in this documentation process, and due to their work on accurately cloning Netscape's JavaScript implementation they knew exactly what odd quirks JavaScript had, and thus what they should make sure to avoid. Or, as it turns out, make sure it got into the standard. Yeah.

This glorious work from Microsoft's side is part of the reason JavaScript is the inconsistent mess it is today. Take for instance how typeof null is "object". That, and a bunch more, is a result of the incredibly short amount of time Eich had to make JavaScript, and Microsoft's effort to make sure all quirks from the original JavaScript implementation stuck in the ECMAScript standard.

Abstraction

Even though it can be tempting to blame Microsoft for everything wrong in the world, it should be said that they aren't the root of all problems with JavaScript. Some of the problems aren't even real problems, but a result of leaky abstractions.

It is fairly obvious that JavaScript tries to be fairly abstract. Take for instance how it doesn't have types. That's an abstraction. Internally, the computer does distinguish between text, integers, numbers with decimals, booleans and more. The JavaScript language tries to hide this however. In the world of JavaScript, everything's a "variable", declared by the keyword var.

One problem which almost exploded in my face is related to how some of JavaScripts types are passed by reference, and others by value.

Now some of you may never have heard of passing values by reference or values is. Nor do you understand why it's a big deal. Even if you're a programmer, this can be a completely foreign concept for you. If that's the case, chances are you're using a very abstract language like JavaScript.

I won't get too much into the inner workings of computers, but I will try to explain the basics of passing by references and values.

Say you have two variables, Foo and Bar. Say you set Foo to 5:

Foo = 5

Now, we set Bar to Foo:

Bar = Foo

If we pass by value, Bar and Foo will be two distinct, completely unrelated variables. Changing one will never ever in a billion years affect the other.

If we however pass by reference, Bar isn't a value in itself. When someone ask what Bar is, it simply says "go check out Foo, maybe he knows"; Bar is what we call a pointer. Because of this, when you change Foo, Bar's value also changes. If we set Foo to 10, Bar is also set to 10. This also works the other way around, at least in JavaScript. If we set Bar to 12053, Foo will be set to 12053. The two variables are the same, just under different names.

Passing by reference can be a lot faster when dealing with big variables. Therefore, JavaScript passes some types by reference. Those types are functions, arrays and objects. The problem here is that when programming in JavaScript, there's no clear distinction between types. After all, that's the point of being an untyped language isn't it?

This can cause some really confusing quirks. For instance, after this code, bar is 10:

foobar = 10;
bar = foobar;
foobar = 20;

while after this code, bar.val is 20:

foo = {"bar": 10};
bar = foo;
foo.bar = 20;

If you're not experienced in JavaScript, or programming in general, this might not make a lot of sense to you. Trust me though when I say that this can cause severe problems.

Of corse, the whole problem would be gone if JavaScript by default passed values by value. Passing by reference could be an option. This is how C does it, and it works great.

There are other quite freaky abstractions out there. Take for instance how JavaScript doesn't force you to use semicolons at the end of lines. It does this by automatically inserting semicolons where they are missing. One of the ways it does this is really creepy: it runs a line of code, and if it fails, it inserts a semicolon at the end and tries again. There are a few problems caused by this which I wont get into, but most of all it's just creeping me out to know that JavaScript does that. It does also teach new programmers the horrible custom of ignoring semicolon, so using languages where semicolons are required becomes a hell. Therefore, use semicolons!

Solutions

What can we do to make our web programming lives easier, and overcome JavaScript's flaws?

One of the solutions can be to translate other languages to JavaScript. Lots of such translators have been made, and nowadays you can translate pretty much any language C, C++, C#, Java, you name it into JavaScript. People are even designing languages whose sole purpose are to be translated into JavaScript code. CoffeeScript is an example of this. A problem with translating other languages however is that the web browser will still be running JavaScript code, and will spew out errors in the JavaScript code. It can't magically know where in the code you wrote the error is. This adds a lot of complication to debugging, and you pretty much have to be fluent in JavaScript anyways to be able to see what the error really is.

Another solution is to simply go with JavaScript, learn to love its quirks, or at least learn how to overcome them. Know that when you typeof null, it will return "object". Learn that if you declare variables certain ways, they are objects, arrays or functions, and as such are passed by reference, and learn what passing by value/reference really means. Learn to always have your Google machine ready. Learn that while high levels of abstraction makes languages a lot easier to get involved with, it also makes it quite a bit harder to really get to know the language.

(some of the things I've written here, I learned from a talk about JavaScript. I think the talk was by Douglas Crockford. Sadly I can't find it again.) As some of you may know, I'm a fan of JavaScript. Pretty much all of my projects are web apps, and as such, JavaScript is an important part of them.

Read More