Behold: the “hate speech”.
- Interpreted languages are too bug-prone
- Callback hell, or how easily you can lose track of what’s going on
- Awkward equality comparers,
==
,===
are infuriating this
is a mess- Anything goes. Loose typing, how pretty much everything can mutate into anything without notice
- Nonsensical behavior like
parseInt('08') === 0
(this one changed recently for V8) - Poor support for (classical) debugging, such as reasonable stack traces
- Prototypal vs Classical inheritance
- All things JavaScript suck
I disagree with most of the above, and I want to spend a few words addressing these concerns.
First of all, the vast majority of these concerns arise from the paradigm shift people experience when developing in JavaScript. Most people are accustomed to a compiler telling them when something is amiss. In JavaScript, however, there is no compiler, JavaScript is interpreted as it is executed. There are a few ways to work around (or mitigate) this concern.
One way to mitigate the impact of not being able to compile your code, is use strict
. By the way, MDN is an extensive resource library on JavaScript you are not using enough.
use strict
in JavaScript is reminiscent of Option Explicit, back in the Visual Basic 6 days. It’s merely a safeguard against silly mistakes, but it comes in handy.
A more definitive approach to solve the issue is to resort to a JavaScript compiler, such as CoffeeScript, or TypeScript.
I discourage taking this approach. Not only because languages like CoffeeScript tend to be very opinionated about how your code should look like, but most importantly, it isn’t JavaScript, it’s an entirely different language; even though it incidentally compiles to JavaScript.
The notion of using TypeScript is slightly less infuriating, since it’s a superset of JavaScript, rather than a different language.
Having said that, the fact that both compilers output pure JavaScript remains, which is reason enough to learn how to code in JavaScript properly by yourself, rather than have a layer of abstraction making coding style choices for you. It’s not like JavaScript is MSIL. MSIL is really hard to read, maintain, write, and everything in between, and generally not worthwhile to code in, unless you need to fine-tune performance, dynamically generate classes, or the like.
A “simple” program in MSIL might be:
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] int32 num)
L_0000: ldc.i4.0
L_0001: stloc.0
L_0002: br.s L_000e
L_0004: ldloc.0
L_0005: call void [mscorlib]System.Console::WriteLine(int32)
L_000a: ldloc.0
L_000b: ldc.i4.1
L_000c: add
L_000d: stloc.0
L_000e: ldloc.0
L_000f: ldc.i4.s 10
L_0011: blt.s L_0004
L_0013: ret
}
JavaScript is not that obscure. JavaScript can be learnt. Compilers hinder your ability to do that. You should learn what a closure is. How to extend a prototype. How to use callbacks sensibly. There lies the real beauty of JavaScript code.
Demystifying JavaScript
- Interpreted languages are too bug-prone
While it might be true that JavaScript code is harder to debug, and can definitely be harder to maintain when improperly structured. There are several tools at our disposal to prevent chaos.
You should treat JavaScript as you would any other language, and as such, you should Unit Test your code. There are several frameworks to pick from.
Client-side JavaScript might prove harder to structure than JavaScript in Node.JS. Frameworks like Backbone.js and Knockout.js can help you structure your code cleanly and without making an unmaintainable mess out of it.
- Awkward equality comparers,
==
is infuriating
This one I’ll concede. The equality operators, ==
and !=
are a mess… They try too hard. If the values being compared are of different types, these operators will attempt to coerce these values using complicated rules that are not even transitive. Avoid them entirely. Use, as Crockford puts it, the “good operators”: ===
and !==
. These return false in case of type mismatch, as would be expected.
this
is a mess
We know how this
story goes. I’ll illustrate with a bad example:
function Car(opts){
this.wheels = opts.axles * 2;
return this;
}
var compact = new Car({axles: 2});
var truck = Car({axles: 5 });
Now compact is a four-wheel car, while our Window became a truck, and suddenly has 10 wheels. Furthermore, this
can be chosen through Function.prototype.apply
, and otherwise changes depending on the context it’s being evaluated in.
Well, you have two options. One option is to ignore the damn thing, and don’t use this
or new
, after all, ignorance is a bliss. The other option is, you guessed it, learning how it works.
- Anything goes. Loose typing, how pretty much everything can mutate into anything without notice
This one is, in my opinion, one of the biggest selling points in favor of JavaScript, which is more often confused with a drawback against the language. I’d rephrase this as JavaScript just works, in that whatever change you want to introduce to your code, JavaScript can accomodate. And as long as you are conscious about maintainability, such flexibility shouldn’t become a problem.
- Nonsensical behavior like
parseInt('08') === 0
(this one changed recently for V8)
There are many oddities like this in JavaScript, more than in some other languages such as C#, fewer than in others. Most of these oddities are easily avoided, and their persistance stems from poor implementations in some web browsers. Others (such as for..in
problems), simply come from the nature of a prototypal inheritance model.
- Poor support for (classical) debugging, such as reasonable stack traces
Often overlooked is the ability to execute code on demand in a browser console, or writing debug messages which you can see in real time with no extra frameworks, and without altering the user experience. These are things you often can’t do in other languages either, once you get accustomed to these, you’ll find it way more productive to debug with a console and hacking away at the DOM, than to step through your code, and recompiling every time you add a comma.
- Prototypal vs Classical inheritance
In JavaScript, things inherit from other things, and not from abstract concepts (or classes). This might be hard to wrap your head around if you are experienced in class-based languages such as Java or C#, but you’ll soon get over it, and begin reaping the benefits.
Conclusion
JavaScript is awesome, and you should love it more!
Comments