For modern development, JavaScript indeed is a s**t-disappointing language.
I'm sorry, but the Crockford arguments do not cut it.
JavaScript is terrible in many ways and extremely boring. I can't understand why everyone is so enthusiastic about jumping into the Node learning bandwagon. Yes, Node is faster than Ruby, and it's event-driven, but what baffles me is that some people want to rewrite their programs in Node at every opportunity—can't they use their brains?!
JavaScript's inheritance and deep copy issues cannot be solved by defining a new ECMAScript standard, nor by wrapping it with fancy syntax (like CoffeeScript), or even by standardizing with require or introducing classes. Isn't there an ActionScript in the ECMAScript family that introduced classes? That thing is just as bad as JavaScript. As long as people keep using it, the current state of PHP frameworks will be the future of JS—a never-ending stream of people working day and night to build frameworks and tools for this crap language.
Let me explain why JavaScript is awful. Of course, it has its good sides too. But the problem is that it's impractical. For example, prototypal inheritance has many limitations—it's essentially function overriding. And the idea of "everything is a function" is quite useless because functions are not objects and cannot serve as data structures to carry data.
In fact, the real complaints are just beginning. Here are a few examples:
JS's property invocation
This design is crap. Looking back, it's hard to blame the language designers since they might have prioritized performance. Moreover, if you're not familiar with message-passing languages, you'll wonder why some properties can be invoked while others cannot!
Hash objects are not available for stable keys
Mixing objects and hashes is not a good idea because it violates the premise that objects can have metadata. Metadata allows us to establish basic type systems or at least various types of introspection.
Function objects are not usable for type systems because an object carries no type information
This is a big deal. In Ruby, everything quacks like a duck happily. We often use Object.class to get object information. Below is the standard process for styling HTML elements:
' id=''>…
This is impossible in JS because only 'Object', 'function', and primitive types carry type information.
Everywhere is Null
You accidentally misuse a constant.
MyApp.SYNC // should have been MyApp.SYNC_FETCH
Nothing happens because objects are hashes, and JS defaults constants to 0. A constant with an incorrect key will be undefined and will propagate into the called function. When things go wrong, you’ll have to track and debug it yourself.
The Abyss of Callbacks
JS lacks proper deferred functionality. Without multithreading, it relies on event-driven execution. Your calls are scattered across various event callbacks, and the code finishes executing while the callbacks are still running. For example, doing something like this in JS is cumbersome:
var res = await AjaxReq.fetch('/long-request'); // because you're waiting for a result, here the runtime would schedule event handling, DOM redraws, and whatever else it can squeeze in while you await;
res.name; // this will only execute once res is available;
While you're waiting for a result, the runtime can handle events, redraw the DOM, and do anything else it can fit in during the wait.
res.name — executed once res becomes available.
Of course, the JS community does the same thing the PHP community has always done—clean up after JavaScript’s mess by adding more callbacks. The better ones are callback chains:
when( // 48 lines down)
.then( // 23 lines down)
.then();
In general, adding a wait primitive controls events while waiting for results.
A professional approach is to make everything asynchronous, but realistically, 80% of your code is synchronous because 80% of programming involves coordinating two f*cked-up things, and you need both of them to finish.
Terrifying Exception Handling Mechanism
Exception handling in JS is terrifying. Typically, you can see the call stack (a bunch of anonymous functions and some well-named ones) and the error messages. Here are two common errors:
undefined is not a function
cannot call property 'xyz' of undefined
This is all thanks to JavaScript’s "f*cking" function objects, which lack method definitions—they only have properties. The JS runtime can never know whether a function object has callable methods or if a property name exists—it assumes your hash key doesn't exist.
I remember people in the Ruby community complaining about Ruby's backtrace and error message mechanisms. Rubinius fixed it. In f*cking JavaScript, do you know how messy the error messages can get? Because the two most basic and important exceptions, NameError and NoMethodError, could occur, which is incomprehensible in other languages but somehow acceptable in JavaScript.
Undeniably, functions are a highlight, and prototypes are good things. But if you want to build a slightly complex JS application, you'd have to write something like this:
var cv = Marionette.CollectionView.extend({
itemView: MyApp.Views.WidgetView;
});
What error would you get if "MyApp.Views.WidgetView" is not defined? "undefined is not a function." Of course! When would you get it? When CollectionView tries to instantiate your view—not when you define the variable cv. You'd be anxious for minutes until you figure out where the error came from.
Why? Because everything is a hash, and the language cannot perform any form of introspection.
Another thing that bothers me is that some people switch from Ruby to Node and praise Node as a good thing. Maybe Node is a nice gem, but knowing it runs on a sh*tty JavaScript language inside makes me want to stay far away.
To put it simply, as long as JS remains unusable, I won't touch Node, thank you.
I understand why some people want to move from MRI to Node—it's simple. You don't speak Japanese, so you pretend it's hard to learn. The truth is, your chances of improving on MRI are approaching zero.
JS is s**t. If we had any sense of responsibility, we'd either help it improve or let it die. Being complacent and praising it doesn't help its development. CoffeeScript is still not enough.
Update: Look here, I'm not alone in this fight.
Translator's note: The julik live blogger later changed the title to "For modern development, JavaScript indeed is a s**t-disappointing language." Also, his blog footer was criticized by many readers for being ugly and taking up too much space. Of course, some热心netizens are already offering suggestions to help him improve it.
Translated by: Bo Le Online - Huang Limin
Translation link: http://blog.jobbole.com/50671/