
JavaScript is Dead. Long Live JavaScript - peroo
http://peter.michaux.ca/articles/javascript-is-dead-long-live-javascript
======
kbd
Great and thorough article. Here's a TLDR:

* Javascript has some warts, and here are some examples.

* It's going to take way too long to get these fixed to the point that we can actually start using new versions of Javascript because of slow browser adoption.

* To get around this problem, people are treating Javascript as a compilation target for other languages, the most prominent example being CoffeeScript.

* Discussion follows of features that would make Javascript better serve its increasing role as a compilation target.

* There is discussion of Harmony throughout.

Sometimes offering a TLDR indicates that the article isn't worth reading "so
here are the author's points so you can skip it". That's not the case here.
For example, I learned about "Tennet's Correspondence Principle", which helps
to give a name to the different ways procs/blocks and methods/lambdas behave
in Ruby, as explained in this article[1].

[1] [http://www.robertsosinski.com/2008/12/21/understanding-
ruby-...](http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-
procs-and-lambdas/)

~~~
Joeri
"It's going to take way too long to get these fixed to the point that we can
actually start using new versions of Javascript because of slow browser
adoption."

Which isn't true, because you could compile newer versions of javascript to
older versions. I see languages like coffeescript as interesting experiments
in how the language can evolve, but eventually it needs to come back home to
javascript and get deployed natively in browsers.

~~~
bgrohman
Good point. I hadn't thought of compiling old versions of javascript to new
versions - that keeps everyone writing in the same language and seems like a
better solution to me.

~~~
petermichaux
There was an ES4-to-ES3 compiler. The Traceur compiler takes many of the
Harmony ideas and compiles to ES3.

------
masklinn
> If your application uses the let idiom, wouldn’t it be nice to have new
> syntax for it?

Mozilla introduced this back in Firefox 2, and you can replace var with it, so
TFAA's

    
    
        for (var i=0, ilen=elements.length; i<ilen; i++) {
            var element = elements[i];
            let (num = i) {
                LIB_addEventListener(element, function(event) {
                    alert('I was originally number ' + num);
                });
            };
        }
    

becomes:

    
    
        for (let i=0, ilen=elements.length; i<ilen; i++) {
            let element = elements[i];
            LIB_addEventListener(element, function(event) {
                alert('I was originally number ' + i);
            });
        }
    

Of course, since this does not quite seem to be a tight loop you should be
using Array.prototype.forEach instead:

    
    
        elements.forEach(function (element, i) {
            LIB_addEventListener(element, function(event) {
                alert('I was originally number ' + i);
            });
        });
    

> The JavaScript idiom that potentially spans the most lines of your program
> may be the inheritance idiom.

That's not an idiom. And there are numerous implementations of classes on top
of prototypes out there, if there's one javascript "problem" which does _not_
need new syntax it's that one.

~~~
bzbarsky
Actually, the forEach version can end up faster than the let version...
especially if you self-host forEach so that the JIT can do its job (e.g.
inlining the LIB_addEventListener calls so there aren't actually any function
invocations, etc).

~~~
masklinn
> Actually, the forEach version can end up faster than the let version...

Theoretically maybe, but I've yet to see that. A regular `for(;;)` is
generally 3-5 times faster than using `Array.prototype.forEach`.

Re. JIT, hand-rolling a foreach in javascript can be up to twice as fast as
the native one, depending on the features you leave out.

~~~
bzbarsky
> Theoretically maybe, but I've yet to see that

Compare the let version to the code in
<https://bugzilla.mozilla.org/show_bug.cgi?id=602132>

------
nxn
"Optional Parameters and Default Values"

Since JavaScript will still invoke a function call even if the number of
arguments don't match up, parameter defaults will not completely eliminate all
the problems he lists.

    
    
      function(a = 1, b = "Smith", option = {}) { .. }
    

Will still break upon trying to invoke it without parameter 'b' since param
'option' will just take its place while option will become an empty object.

Furthermore he argues against "option = option || {};" only to do the same
thing in the function header: "function(a, b, option = {}) { .. }"? What
difference does that make?

The whole section in my opinion is negated by passing object literals to
functions. Stuff like:

    
    
      func({ a: 1, b: "Smith", option: { .. });
    

That makes it easy to read and easier to handle since names are agreed upon by
both the caller and the function handling the invocation:

    
    
      var opt = config.option || {};
    

This is a common practice in JavaScript already, and it beats the solutions he
wished were added to the language.

~~~
Groxx
I'm very much in agreement with objects-as-named-params. Default params just
mitigate the problem, ambiguous function calling still rears its head as soon
as you have multiple optional arguments of the same type.

As to the "option = option || {}", he was referring to the ultimate "option =
{}" assignment if you _passed_ a falsy value (0, "", false), which is
different than if you _didn't_ pass a value (undefined). Which is resolved by
"option = option === undefined ? option : {}", which is even larger and kinda
ugly.

~~~
nxn
Ahh, I see. The thing is, I can't think of a single way to make {} be treated
as false in the boolean context, so 1) I don't think you'd ever need anything
more than "option = option || {}", 2) I think the example would have been
better off using an integer or string where you actually might have to use the
ugly long format.

EDIT: Unless of course you get some non object value passed in and you want to
be sure to keep it regardless of whether or not it is falsy. Not sure why
you'd want to do that -- I am sure I would NOT like to see someone do that if
I had to deal with their code.

------
clintjhill
"Do you want to maintain a compiler? Does anyone on your team have the skills
to do that? That ulcer is going to get pretty big while you prepare to explain
to the CEO that you now need to rewrite the UI in JavaScript."

GWT could be really strong. But it's this single maintainer problem that I
think prevents it's penetration into the market.

Sadly when I hear people talk about the "strengths" of GWT, debugging and IDE
debuggers is what I hear most. If that is the core reason for using GWT it
seems shortsighted.

And for me personally I find that using Java (static typed system) to compile
down to JavaScript (dynamic function system) is too big a paradigm switch for
developers to maintain. Other languages, specifically functional type
languages are far better for maintaining language paradigms in compiler
situations.

~~~
grimlck
Why isn't the 'single maintainer problem' a concern with other programming
languages? What language DOESN'T have a single organization leading its
development? Even worse, some projects (incl. coffeescript) seem to be
controlled by just a handful of individuals who can easily be hit by a bus,
hired away to do something else, lose interest, etc.

I think the only way to defend against that is to have an open source project,
and to have a sufficiently large user base such that someone is sure to take
over if the owners drop the project.

I think the strength of GWT is that for some languages/teams, a statically
typed language is more appropriate than a dynamic language. And isn't more
choice a good thing? Avoid the whole 'this is a hammer, everything else is a
nail' approach?

I do agree that some teams choose GWT for inappropriate reasons though.

~~~
clintjhill
Good questions/points.

I would only respond with that in particular, GWT is more than a compiler - it
is as much a JRE as anything. So there is more to it. I personally don't see
Google doing much public interaction with the development of the GWT compiler.
If it's left to Google and its own time then my point remains.

JavaScript on the other hand really doesn't have a single organization leading
it's development. Maybe this is an argument to be made about its perceived
slow progress. Language design by committee is pretty slow.

More choice is good. Always. But right tool for the job should always win.

------
bartl
He calls inheritance in Javascript a wart. It's one of its major strengths,
IMO: the fact that you can directly override methods for a single object.
Class inheritance, as he'd like to see, is not all it's cracked up to be. Just
look at Java with its anonymous inner classes, for one incredibly ugly
construct...

BTW an easy way to produce traditional class inheritance in Javascript is to
have a single instance from the class you're trying to inherit from, as the
prototype. (To work properly that object should be "abstract": have no ties to
any physical resources, like a browser widget, a database handle or a file
handle.)

~~~
bgrohman
Yeah, javascript's prototypal inheritance is flexible enough to simulate
classical inheritance. I wouldn't call that a wart.

<http://www.prototypejs.org/learn/class-inheritance>

<http://dojotoolkit.org/reference-guide/dojo/declare.html>

Plus, I tend to prefer prototypal inheritance to classical inheritance. I do
agree that the constructor pattern using the new keyword and the prototype
object is a bit odd, but that's not the only way to have objects inherit from
other objects in javascript.

~~~
WayneDB
The wart is that since classical inheritance isn't built into the language, we
get:

1) Crummy syntax. 2) Everybody doing it a different way.

~~~
bgrohman
I see your point to some extent. I don't think the functions for mimicking
classes provided by libraries like Prototype and Dojo have particularly crummy
syntax. But since there isn't a standardized way to create classes,
implementations are usually a little different.

Still, according to this logic, any language that doesn't support classical
inheritance has warts. I'm not sure I agree with that. JavaScript doesn't have
classical inheritance built in, but I haven't seen anything to make me think
that it's really needed from a programming standpoint. Your point #2 is valid,
but could that can be attributed to the programmers who use the language
rather than the language itself?

------
mark_l_watson
He did mention the GWT Java to Javascript compiler. I have been using GWT
(actually SmartGWT) a _lot_ lately because one of my customers uses it. Except
for long build times, the GWT Java to Javascript compiler has a lot going for
it. Once a project is built and running in test + debugger mode, the client
side development experience is pretty good.

------
EGreg
Why not just have a library in Javascript, for example:

    
    
      Q.each(arr, function(i) {
         this.rocks();
         arr.pop(); // watch out doing this in the loop
         arr.push('foo'); // watch out doing this in the loop
      });
    
      Q.each(obj, function(k) {
         this.rocks();
         delete obj[k]; // should be safe maybe
      });
    
      var p = Q.pipe(crazy stuff involving pipes and callbacks)
      doSql("SELECT * FROM users", p.fill('users'));
    
      getUsers = Q.getter(getUsers); // turns it into a really  smart getter
    
      getUsers = Q.batch(getUsers); // turns into into a batched getter
    

and lots of other stuff

Why must the language take care of everything for you when libraries can do
it? That has been the case with C, C++ and other languages.

~~~
petermichaux
Features that can be added through libraries should be added that way. You
cannot add new syntax which involves scoping of variables through libraries.
How would you do destructuring assignments with a library and have it as
succinct as it can be done with syntax?

~~~
EGreg
Yeah, some features can be pushed into the language, but I like languages
which have few rules. Like C and like CHESS :)

My favorite languages are C, Java and Python though. So go figure...

~~~
petermichaux
If you like minimalistic languages, have you checked out Scheme? Because of
its macros, the core language can stay small and the users can expand its
syntax.

------
skarayan
I tend to agree that compiling to JavaScript is the future of browser
programming. CoffeeScript seems to be a nice language, but I bet there will be
many more to come in the next year or two.

~~~
rhizome
I hope someone writes a decompiler for one of these supra-JS languages (not
sure if CoffeeScript is Turing-complete) to run against existing Javascript
codebases. It could well speed up adoption if a mass-tangle of JS can be
boiled down to a more readable and understandable structure.

~~~
apl

      > not sure if CoffeeScript is Turing-complete
    

Wait, why wouldn't it be?

~~~
rhizome
Heck if I know, I'm not CS trained.

Point being, CoffeeScript and other compilers would get a big boost if someone
came out with a way to convert existing JS codebases into these new, more
readable, more maintainable (as the story goes) representations.

~~~
alecperkins
js2cs - <https://github.com/mindynamics/js2cs>

Though I've found doing the conversion manually is a better way to learn
CoffeeScript. Plus, it is a point for optimization and refactoring since
CoffeeScript allows for doing certain things more easily or in better ways.
The automated conversion only does so much.

------
AshleysBrain
What happened to the idea of standardising Mono (the open source .NET)
bytecode as a new browser language?

Then you can use whatever java-like/basic-like/functional-like language you
want, and have it compile to bytecode. Also, with sophisticated JITs for that
style of bytecode already lying around, you could probably instantly beat
javascript's performance even under the best engines, because of static typing
etc. rather than relying on ridiculously complicated static analysis.

It'd have to be supported side-by-side with javascript for the forseeable
future, but the earlier you get a change like this in, the better...

~~~
azakai
1\. JavaScript's speed is actually not far from Mono's now. And constantly
getting closer.

2\. I don't think anyone but Microsoft would support .NET bytecode in the
browser, simply because Microsoft controls .NET and has patents on it. It
would take a lot more to reassure other browser vendors than Microsoft's
existing CPs.

3\. Running _dynamic_ languages on Mono is slow. Look at the speed of all the
dynamic languages on Mono (or the JVM for that matter), and compare them to
native implementations of dynamic languages, in particular JavaScript and Lua.
The native implementations beat dynamic languages on Mono by a large margin,
simply because .NET is a bytecode made for static languages. Of course you can
say that you prefer to have static languages in the browser over dynamic ones,
that's a legitimate opinion of course, but not everyone would agree.

4\. Standardizing on bytecode can inhibit innovation. JavaScript doesn't have
a bytecode standard, which let JS engines implement very different ways of
running it (V8 doesn't have a bytecode interpreter at all, for example). Of
course standardizing on syntax also inhibits innovation, just in other ways,
it isn't clear which is better.

5\. Static languages compiled to JavaScript (that is, that use JavaScript as
their 'assembly') are getting quite fast. Some benchmarks I ran found them to
be around 5X slower (on the development versions of SpiderMonkey and V8) than
gcc -O3, compared to Mono which is 2.5X slower,
<http://syntensity.blogspot.com/2011/06/emscripten-13.html>

6\. There is already Silverlight/Moonlight which does .NET in browsers, and it
hasn't been very successful. (Of course it is a chicken and egg thing, if it
were bundled in browsers it might be more popular. But the failure of
Silverlight is a disincentive to add Mono to browsers nonetheless.)

For all these reasons, I don't think Mono has much of a chance to be included
in browsers. Most of the same arguments apply to other static-language
bytecodes like NaCl.

~~~
nxn
>> 1\. JavaScript's speed is actually not far from Mono's now. And constantly
getting closer.

[http://shootout.alioth.debian.org/u32/benchmark.php?test=all...](http://shootout.alioth.debian.org/u32/benchmark.php?test=all&lang=v8&lang2=csharp)
<\- That still looks sort of far to me.

>> 3\. Running dynamic languages on Mono is slow. Look at the speed of all the
dynamic languages on Mono (or the JVM for that matter), and compare them to
native implementations of dynamic languages, in particular JavaScript and Lua.
The native implementations beat dynamic languages on Mono by a large margin,
simply because .NET is a bytecode made for static languages.

It's not fair to compare JavaScript, which is already approaching a limit of
how fast it can go, with the speed it gets running in Mono. Why? The two
implementations have a vast difference of amount of energy and resources
thrown at them; had Google, Mozilla, and Microsoft wanted JS to run fast on
Mono, it would run fast on Mono.

Also saying that .NET is a bytecode made for static languages is kind of iffy
now that the "Dynamic Language Runtime" is a part of .NET

~~~
azakai
1\. The Alioth results are not necessarily final - they compare a single JS
engine, and we have several fast ones now (SpiderMonkey with type inference
can be significantly faster on some benchmarks, for example). Even so, the
median speed there is 2X, which is fairly close. Admittably there are some bad
cases though, in particular pidigits (badly written benchmark code? bug in
v8?).

2\. It is true that JS on Mono has had far less work done, and that the DLR
exists. However, the fact remains that dynamic languages are a late addition
to the JVM/.NET model. For example, one very important thing for dynamic
language performance is PICs, and to my knowledge there is no good example of
fast PIC performance on the JVM or CLR. In fact, we don't even have a good
example of a generic virtual machine that can run multiple dynamic languages
fast (Parrot exists, but is not that fast) - all the fast dynamic language
implementations are language-specific, so it shouldn't surprise us that VMs
built for static languages don't do that well either.

~~~
nxn
In my opinion it makes no difference that we have several fast engines where
some are faster at some things than others. When executing in the browser you
don't get to pick and chose how and where your application will be executed.
If you run into performance problems on one of the engines you can: A) dismiss
a subset of your users and their performance problems, telling them to use a
browser with a faster engine (they wont), B) only allow certain functionality
based on a user agent string, or C) limit your applications scope to one that
runs suitably in the slowest of the engines you're willing to support. In
essence, if the application runs great in browser A but chokes in browser B,
are you willing to say bye bye to your A users to take advantage of
performance gains on B? I've been in this situation, and in my experience I've
always had to look away from the faster browser rather than the user.

Outside the browser you probably have a little more freedom, but it's not like
you get to pick and chose in the style of "Oh, I'll execute this function in
V8 since it does this faster, and that function in SpiderMonkey since it's
faster there". For this reason, I don't think the fact Alioth only has
measures for one engine would make a significant difference in the overall
comparison. You'd be, for the most part, gaining performance in one place by
sacrificing in another.

Anyway, in my personal experience, I've ran into performance problems in JS a
lot more often than with C#. I also have to go through a lot more tedious
practices to ensure my JS code runs as fast as it can, where as in C#
Some.lookup.with.lots.of.dots.does.not.scare.me(). That's why your claim sort
of surprised me. Then again, the last serious JS performance problem I had was
6 months ago (before FF4), so maybe a lot has happened in those 6 months.

By the way, I'm not too informed on how type inference is done in
SpiderMonkey, so I may be completely wrong in mentioning this, but it sounds
like they're trying to speed up a dynamic language by mimicking static typing.
If that's how far they're going to improve performance, maybe soon enough
JavaScript will in fact sit better in the Mono/.NET/JVM?

~~~
azakai
I agree with your point about multiple JS engines, indeed you can't pick and
choose the best results. What I was trying to say is just that the best
results we see are an indication of where things are going. But again, I
agree, we are not there yet and right now, each user has just one JS engine,
and problems on some benchmarks. Static languages have much more consistent
performance.

About the last 6 months: Yes, a lot happened during that time, namely FF4's
JaegerMonkey and Chrome's Crankshaft. Both are significant improvements.

About typing, yes, in a way that could let this code run faster inside the JVM
or Mono. If you can figure out the types, you can generate fast statically
typed code for those VMs. However, type analysis can be both static _and_
dynamic, should integrate with the PICs and so forth. So even with that, I
don't expect dynamic languages to be able to run very fast on static language
VMs.

------
nxn
"In 1997, I collected a list of languages with compilers to JavaScript. There
were JavaScript extension languages: the now-defunct ECMAScript 4, Narrative
JavaScript, and Objective-J. There were pre-existing languages: Scheme, Common
Lisp, Smalltalk, Ruby, Python, Java, C#, Haskell, etc. There were even brand
new languages HaXe, Milescript, Links, Flapjax that were designed to address
web programming needs."

Am I reading this right? Objective-J (2008), C# (2001), HaXe (2005), etc
having compilers to javascript in 1997?

~~~
petermichaux
You know how on January 10th, 2011 you were still writing 2010 by accident? I
was off by a decade. Corrected.

------
TheOnly92
The key here might not be implementation but adoption.

------
kib2
I maybe wrong but it seems that caterwaul provides a macro system for JS (but
I never tested it): <http://caterwauljs.org>

------
bengarvey
I like the prediction, but I think the biggest hurdle to compiled javascript
will be mobile browser usage. The javascript interpreters in the mobile
browsers right now are dog slow compared to their desktop cousins.

~~~
mbrubeck
Android 2.2 and later uses Google's V8 JIT. iOS 4.3 and later uses Apple's
Nitro JIT. Firefox 4 and Opera 11 also have JIT compilers enabled for ARM
devices.

Mobile processors are still slower than desktop ones, of course, but
JavaScript on mobile today is already faster than JavaScript on desktop just a
few years ago. For example, the benchmarks on <http://arewefastyet.com/> show
V8 running only about 5x slower on an nVidia Tegra 250 ARM board than it does
on an Intel Core 2 Duo Mac Mini.

------
seanp2k
I really hate when "X is dead; long live X!" is misused like this. The
original phrase is "The king is dead; long live the king!", used when the OLD
king died and the NEW king takes over.

Googling around, I see tons of misuse: Example of bad usage: "White Stripes
are dead (long live white stripes)"

Example of proper usage: "Palm is dead; long live Palm!" (this would mean that
Palm got acquired or reformed) "Paper is dead; long live paper!" (could be
proper if used in an article about how paper for PRINTING is dead but paper
lives on in other forms)

REF:
[http://en.wikipedia.org/wiki/The_King_is_dead._Long_live_the...](http://en.wikipedia.org/wiki/The_King_is_dead._Long_live_the_King).

~~~
petermichaux
They didn't say "The King Henry VIII is dead. Long live the King Edward VI".
In the JavaScript article, The "OLD king" is "JavaScript the source language".
The "NEW king" is "JavaScript the compilation target". So the idea of old and
new is in there. Sort of. :-)

------
derrybryson
Improvements to javascript would be great, but none are actually needed, the
language is quite functional as is. Learn how to code or use coffeescript or
develop your own new language to compile into javascript to support whatever
language crutches you need.

