Admitting that Javascript was a Mistake

There was an interesting article that was written by Guillaume Marceau recently about visually expressing the usefulness of programming languages. The article uses star-line plots to show how different programming languages compare with one another in speed and expressiveness, as each is used to solve a number of common problems. It’s always nice to check your gut reaction to different programming languages against empirical evidence. Language choice can be as varied as our food preferences, often not based solely on fact. Like our palate, we may find that our preference for our favorite programming languages change over time. As we learn more and use our language of choice to solve real problems, the initial love affair may turn into a nightmare.

At Digital Bazaar, our initial fondness for Javascript is turning into a deep distaste for the way Javascript has evolved in the browsers…

Wrongful Optimization

In the programming language visualization article, Marceau concludes that there are many functional programming languages that are very fast, compared to C and C++. He also notes that the primary factor that determines the speed of a language is it’s maturity — the number of years that it has been around. In general, one of the primary benefits of functional programming languages is that they provide closure-based programming, lock-less data structures, and eschew saving state that result in a high degree of automatic parallelization and processing throughput for problems that can be easily defined in functional terms. In theory, and sometimes in practice, functional programming is great for quickly processing large swaths of data (speed) or cleverly solving an algorithmic problem with very compact code (expressiveness).

Javascript, while not considered a “pure” functional programming language, relies heavily on functional programming techniques and is where most new programmers are introduced to many functional techniques. The use of Javascript far outweighs the use of most (if not all) functional programming languages like Haskell, and Lisp. This is mainly due to the massive deployment it enjoyed when it shipped with the Netscape browser back in the late 1990s. Javascript is still the primary mechanism for scripting, animating and modifying web pages in the web browser. Javascript has brought us such great applications as Google Maps, Digg, Gmail, Facebook, and Twitter. Recently, we have seen massive speed improvements for Javascript in Firefox, Google Chrome, and Opera. Unfortunately, the speed improvements for Javascript are mostly irrelevant because they optimize the wrong thing.

Note that when Javascript is mentioned in this article, we are talking about not only the language, but the core set of libraries and programming environment as well.

The current focus on Javascript performance largely misses the point of what we’re trying to do with Javascript in the browser — control a graphical user interface. Control of a GUI is something that is “fundamentally procedural”. By “fundamentally procedural”, I mean that there is a list of steps that you must complete in a very specific order, and tying in step interdependencies or GUI state is not straightforward in functional programming languages. To grossly over-generalize, GUIs mesh better with procedural techniques than functional ones.

Attempting to force something that is procedural in nature into a functional programming language, like Javascript, leads to the awful, sinking feeling that you get when something goes wrong in your Javascript code. Couple that with Javascript’s lack of a core set of Web libraries (like jQuery), awful functional debugger support, silent failure by design, over-dependence on closures, and single-threaded processing model and you have the Web as we know it today — shiny on the outside with a lack of substance inside.

9 Responses to "Admitting that Javascript was a Mistake"

Let me rephrase my criticism in a way that might be more constructive:

You’d like to throw out one of the 4 major components of the modern web (http, html, css, javascript) because it’s too slow and not multithreaded, and replace it with … python?

I love python, but to claim that more people are working on python than on javascript is ludicrous.

It is also, by design, only singlethreaded. Meanwhile there’s nothing in javascript that requires it be singlethreaded, google gears already proved that.

I’m sorry that you encountered a performance problem when constructing your site. I don’t think that waving your hands and proclaiming everything to be garbage on the basis of that single use case and your inability to optimize your code to be useful feedback.

I’m not sure what you meant here. Pure functional languages (http://en.wikipedia.org/wiki/Functional_programming#Pure_functions) can’t share data dependencies across functions. By definition a closure is a bundle of data that you’re passing around… it’s an object in the OOP sense. Those functions are closed over the “this” pointer that’s implicitly being passed between them. In pure functions this is forbidden because that bundle is a bundle of mutable state, and sharing it means that you’re impure by definition.

“eschew saving state and lock-less data structures that result in a high degree of automatic parallelization”

I’m not sure I follow. Functional languages like Haskell and Clojure can save state and use lock-free data structures, in fact Clojure goes a step further and uses functional data structures, data structures that can keep a history and allow multiple versions to cohabitate (mostly for thread safety and functional purity reasons).

I think you just made every Haskell programmer hemorrhage. Javascript can do functional programming-like things, like higher-order functions, but makes no effort to do what most functional coders would consider ‘functional programming’ (type theory, kinding, monads, and an array of other techniques no one outside of FP has heard of)

“Control of a GUI is something that is fundamentally procedural.”

This is not correct. GUIs and procedural languages are actually very difficult to wrap together, as those who struggled through the early years of GUIs remember. How many times using an application have we said “yes, I know you’re loading, but why can’t I click ahead of time and tell you what I want?” The idea that well-behaved GUIs need multiple threads says something of the shortcomings of procedural programming.

“Attempting to force something that is procedural in nature into a functional programming language, like Javascript, leads to the awful, sinking feeling”

Going along with what I mentioned earlier, there’s a field of research specifically aimed at things like GUIs called reactive programming (I’m not sure how much Wikipedia article will help v. confuse – caveat lector: http://en.wikipedia.org/wiki/Reactive_programming). The gist of the idea is that things like GUIs have events, events are reactive in nature, not imperative. You don’t tell the application to push the button, you push it and then it reacts to you. What happens after that should be able to mix with other events safely.

“Empirically Disliking Javascript”

Besides the comments about closures and threading, most of your complaints here are tools or library-related. I don’t think it’s fair to dock JS points when you’re not commenting on it directly.

“Python does just fine when as a multi-threaded app or when running as an event-driven program.”

Not sure what you mean by “just fine”. Though you can “make it work”, threading in Python is generally worse that most other languages because of its global interpreter lock. Some work has gone into fixing this, but Guido is less than optimistic: http://www.artima.com/weblogs/viewpost.jsp?thread=214235

“procedural Model-View-Controller programming model.”

MVC is actually a fairly tepid approach, as it makes no allowances for reuse or testing, it spreads state around, has few patterns for deeply parallelizing your application, or responding to events (you can shove them in controller and call them from view, but you really want an async third party doing this for you so you don’t taint yourself with implementation details), or sorting your functionality into expert domains, enabling flexible “scripting” layers between engine and changing requirements, or… I’ll stop there, you get the drift.

Sadly, I’m not saying I have a better 3-letter acronym. I wish I did.

“we are going to have to empower web developers by fundamentally rethinking the Javascript mistake”

I’m going to assert, and this is just my opinion, that Javascript did more for the web than you’re giving it credit for. It’s terse, it’s familiar (C-like or Java-like), and it’s quick. Yes, you can come up with lots of bad designs with it. But it gets things done, and has some bonus higher-order things built-in. The end result is far less rigid than it might have been. Imagine if we’d had to program our web pages in C… could there ever have been a hobbiest web developer revolution?

“Things are getting better, and they could be much worse â€” at least it wasnâ€™t HTML+Lisp.”

What?! You might not like the parentheses… I’ll grant you that. But I could easily imagine a Lisp-driven browser that isn’t affected by most of your JS issues, while having the bonus of being generally faster. Not to mention we wouldn’t need things like base object extension toolkits because in Lisp things are far more compositional in nature (by design).

Not to say that Lisp is perfect, but I’m continually stunned at how much comes from the Lisp community. I doubt OOP would have progressed as far as it has without closures and CLOS. Aspect-oriented programming wouldn’t have been possible without metaobject protocols. Lambdas, garbage collection, REPLs, metaprogramming… lots of stuff was born and developed in Lisp before they found their way into other languages.

dbt wrote: Youâ€™d like to throw out one of the 4 major components of the modern web (http, html, css, javascript) because itâ€™s too slow and not multithreaded, and replace it with â€¦ python?

No, I don’t think throwing Javascript out completely would be the most beneficial thing at this point. I think Javascript needs some competition as it’s the only contender for in-browser web scripting languages.

Hindsight being what it is, I do think that it was a mistake to use it as the primary client-based scripting language due to it’s functional/closure nature.

There are more reasons than “it’s not multithreaded and is slow” that I listed – they all contribute. The main point of the article, is that we’re using functional mechanisms to solve procedural problems. Javascript’s programming paradigm just doesn’t fit well with the fundamentals of managing a GUI.

dbt wrote: I love python, but to claim that more people are working on python than on javascript is ludicrous.

Yes, that would be a ludicrous claim – mostly because I don’t know how many people are working on Python and how many are working on Javascript. You will also note that I never make that assertion in the entire article. The point I am making is that browser vendors should re-use a good scripting language and create a set of core, cross-browser libraries. Javascript adds no clear benefit that I can see over Python and Ruby.

dbt wrote: It is also, by design, only singlethreaded. Meanwhile thereâ€™s nothing in javascript that requires it be singlethreaded, google gears already proved that.

When you manage a GUI with a single threaded execution environment, your GUI stutters. This is due to the rendering thread and the processing thread not being independent of each other. Granted, this is a gross oversimplification of what currently happens in most modern web browsers, but the idea of separating rendering, processing and communication into separate threads of execution is a lesson we learned in the early 1990s… and we forgot just 5 years later.

You are correct about there being nothing in Javascript that requires a single-threaded execution model – but single-threaded is how most browsers run Javascript code. What’s important isn’t what is theoretically possible – it’s what is implemented across all browsers. What is widely implemented is not Google Gears nor WorkerPools.

This is, thankfully, changing with HTML5 and WebWorkers. However, speed is just one of the side issues – the main one being the functional nature of Javascript coupled with how the majority of problems are solved with closures.

dbt wrote: Iâ€™m sorry that you encountered a performance problem when constructing your site. I donâ€™t think that waving your hands and proclaiming everything to be garbage on the basis of that single use case and your inability to optimize your code to be useful feedback.

It’s unfortunate that you feel the blog post isn’t useful. Naturally, I don’t agree with your “hand-waving” statement as I listed specific examples and specific solutions. I never stated that anything was “garbage” – just that using Javascript’s functional/closure-based approach to solve GUI problems was, and continues to be, a mistake.

dbt wrote: (side note: doesnâ€™t flash also use actionscript, which is just javascript?)

Technically, it depends on which version of Flash you’re using. The latest versions of Flash use ActionScript 3.0 with is based on the 4th edition draft of ECMAScript, which is different from Javascript (they’re not interchange-able). Also, if you look at how ActionScript is used to drive a GUI and how Javascript is used to drive a GUI, the difference is night-and-day. ActionScript takes a far more (and rightly so) procedural approach than Javascripts functional/closure-based nastiness.

Jon wrote: Iâ€™m not sure what you meant here. Pure functional languages (http://en.wikipedia.org/wiki/Functional_programming#Pure_functions) canâ€™t share data dependencies across functions. By definition a closure is a bundle of data that youâ€™re passing aroundâ€¦ itâ€™s an object in the OOP sense. Those functions are closed over the â€œthisâ€ pointer thatâ€™s implicitly being passed between them. In pure functions this is forbidden because that bundle is a bundle of mutable state, and sharing it means that youâ€™re impure by definition.

Good point, I’ve updated the sentence by removing the word “purely”.

Manu wrote: â€œeschew saving state and lock-less data structures that result in a high degree of automatic parallelizationâ€

Jon wrote: Iâ€™m not sure I follow. Functional languages like Haskell and Clojure can save state and use lock-free data structures, in fact Clojure goes a step further and uses functional data structures, data structures that can keep a history and allow multiple versions to cohabitate (mostly for thread safety and functional purity reasons).

Hmm, I was speaking generally, which I probably should not have done. I was attempting to express some of the benefits of functional languages and why a developer might choose to use them. That particular sentence has been updated to add “In general” at the beginning and some general cleanup of the grammar that will hopefully make the goal of the sentence more clear.

Jon wrote: I think you just made every Haskell programmer hemorrhage. Javascript can do functional programming-like things, like higher-order functions, but makes no effort to do what most functional coders would consider â€˜functional programmingâ€™ (type theory, kinding, monads, and an array of other techniques no one outside of FP has heard of)

I agree that the sentence is not technically correct, I’ve updated that sentence to read:

Javascript, while not considered a “pure” functional programming language, relies heavily on functional programming techniques and is where most new programmers are introduced to many functional techniques.

You could argue that all object oriented languages are functional in nature, or you could simultaneously argue that most popular object oriented languages are not considered “functional languages” by the functional language die-hards. I see can see both arguments.

My point is that most developers first introduction to functional programming will be Javascript these days – not Lisp, Haskell, or any of the other functional languages. While I can appreciate the pure functional languages, like Lisp and Haskell, I have never been much of a fan of “pure” languages when it comes to implementing solutions. Pure languages tend to lead to language ideology rather than addressing real problems. I think it’s safe to say that Javascript solves more real-world problems today than Haskell and Lisp ever did.

Manu wrote: â€œControl of a GUI is something that is fundamentally procedural.â€

Jon wrote: This is not correct. GUIs and procedural languages are actually very difficult to wrap together, as those who struggled through the early years of GUIs remember. How many times using an application have we said â€œyes, I know youâ€™re loading, but why canâ€™t I click ahead of time and tell you what I want?â€ The idea that well-behaved GUIs need multiple threads says something of the shortcomings of procedural programming.

I meant “procedural” in the sense of “there is a list of steps that you must complete in a very specific order, and tying in step interdependencies or GUI state is not straightforward in functional programming languages”. I can see how that concept is not conveyed in the sentence, so I’ve tried to re-word the paragraph to convey the idea a bit more clearly.

I’m not attempting to state that procedural languages are perfect – they’re not. Just attempting to generalize our collective experience that writing a moderately complex GUI in Python, Java and Flash is so much easier than writing a GUI in Javascript. I should also note that the supporting libraries make a huge difference when it comes to writing GUIs – of which, in-browser Javascript, has precious few good GUI libraries.

â€œAttempting to force something that is procedural in nature into a functional programming language, like Javascript, leads to the awful, sinking feelingâ€

Going along with what I mentioned earlier, thereâ€™s a field of research specifically aimed at things like GUIs called reactive programming (Iâ€™m not sure how much Wikipedia article will help v. confuse – caveat lector: http://en.wikipedia.org/wiki/Reactive_programming). The gist of the idea is that things like GUIs have events, events are reactive in nature, not imperative. You donâ€™t tell the application to push the button, you push it and then it reacts to you. What happens after that should be able to mix with other events safely.

Reactive programming can be performed in imperative languages. Even the page that you linked to has a section on “Reactive Imperative Programming”. I’m on board with most of the reactive programming techniques, since that’s how procedural call-back based GUIs are implemented.

Manu wrote: â€œEmpirically Disliking Javascriptâ€

Besides the comments about closures and threading, most of your complaints here are tools or library-related. I donâ€™t think itâ€™s fair to dock JS points when youâ€™re not commenting on it directly.

The article is meant to be constructively critical of what we use the Javascript environment for today – that is, in browser web page control and processing. I don’t mean to dock the language points, I’m critical of the Javascript environment and programming model as it is used in web browsers.

Manu wrote: â€œPython does just fine when as a multi-threaded app or when running as an event-driven program.â€

Not sure what you mean by â€œjust fineâ€. Though you can â€œmake it workâ€, threading in Python is generally worse that most other languages because of its global interpreter lock. Some work has gone into fixing this, but Guido is less than optimistic: http://www.artima.com/weblogs/viewpost.jsp?thread=214235

“Python is capable of running as a multi-threaded app today or running as an event-driven program.”

You could argue that Javascript is capable of running as a multi-threaded app as well, but that hasn’t been what is implemented.

The point I was attempting to make was that this whole single-threaded approach is fundamentally broken and artificially limiting. We should look at each browser tab as a VM instance. The instance should have proper process bean-counting to ensure a single tab, or all tabs collectively, cannot overwhelm a browser by using too much memory, CPU, network connections, disk space, etc. Only recently has Google Chrome introduced the concept of separate VM instances on a tab-by-tab basis – which is heading in the right direction.

Manu wrote: â€œwe are going to have to empower web developers by fundamentally rethinking the Javascript mistakeâ€

Iâ€™m going to assert, and this is just my opinion, that Javascript did more for the web than youâ€™re giving it credit for. Itâ€™s terse, itâ€™s familiar (C-like or Java-like), and itâ€™s quick. Yes, you can come up with lots of bad designs with it. But it gets things done, and has some bonus higher-order things built-in. The end result is far less rigid than it might have been. Imagine if weâ€™d had to program our web pages in Câ€¦ could there ever have been a hobbyist web developer revolution?

Yes, Javascript certainly did do more for the web than I’m giving it credit for.

However, I think you could replace “Javascript” with any of the more modern procedural scripting languages, like Python, Ruby, Perl, PHP and even VBScript and make the same statement. My point is that there is nothing special about Javascript that made the hobbyist web developer revolution happen – any of the scripting languages that I listed would have been able to do that.

â€œThings are getting better, and they could be much worse â€” at least it wasnâ€™t HTML+Lisp.â€

What?! You might not like the parenthesesâ€¦ Iâ€™ll grant you that. But I could easily imagine a Lisp-driven browser that isnâ€™t affected by most of your JS issues, while having the bonus of being generally faster. Not to mention we wouldnâ€™t need things like base object extension toolkits because in Lisp things are far more compositional in nature (by design).

Not to say that Lisp is perfect, but Iâ€™m continually stunned at how much comes from the Lisp community. I doubt OOP would have progressed as far as it has without closures and CLOS. Aspect-oriented programming wouldnâ€™t have been possible without metaobject protocols. Lambdas, garbage collection, REPLs, metaprogrammingâ€¦ lots of stuff was born and developed in Lisp before they found their way into other languages.

There is a Lisp-driven browser – Emacs/W3

I have a great deal of respect for Lisp and it’s contributions to other languages. Certainly we can trace many of the features in Javascript, Ruby and Python back to Lisp. However, can you imagine controlling an HTML DOM with Lisp? If not, here’s a very small example of what it would look like (taken from Generating HTML with Lisp):

You could argue that all object oriented languages are functional in nature, or you could simultaneously argue that most popular object oriented languages are not considered “functional languages” by the function language die-hards. I see can see both arguments.

Right, which is why I avoided that, opting to point at languages like Clojure and Haskell(and ML) as opposed to Lisp. In some sense, even Lisp isn’t a functional language, but if we include closures in our definition, then you’re right, both Lisp and Javascript (or JavaScript or ECMAScript… no clue what the correct name is these days) fall under a similar category.

I donâ€™t mean to dock the language points, Iâ€™m critical of the Javascript environment and programming model as it is used in web browsers.

Perhaps the title should have been “Admitting that Current Javascript Environments Are Inadequate” or something like that.

any of the scripting languages that I listed would have been able to do that

Definitely a fair point. I could imagine most scripting languages would be just fine where JS is. Though, I think this weakens your title thesis of “Admitting that Javascript was a Mistake”. It wasn’t, no more than picking Python might have been.

I’m sure we can find particularly mealy examples in many successful languages. For example, C++’s template facilities allow you to create vectors of any type, instead of having to write a new vector class for each type you want. But the templates also make for some hairy code in the details.

Your Lisp example is a “defmacro” example, which is similar to C++ templates, but more powerful. It’s going to be a bit hairier than the code the user would see. Think library coder v. everyday coder. The library coder will be generally more skilled, and will need more serious tools, so that he/she may support the user more completely.

Cribbing from the Clojure book I just got, this is what I’d imagine most HTML/Lisp users would see:

Take a look at Aptana Studio, and its JavaScript debugger. I’ve been using it for the last few months on an all-JavaScript application, and it has saved me more time than I can count on my fingers, toes, and other appendages.