Admitting that Javascript was a Mistake

A replacement for Javascript

The browser manufacturers should get out of the business of writing programming languages and defer the development of a web language to those that have the resources to focus on it full-time. The Python community would be a good candidate. For starters, Python would solve the following Javascript issues:

  • Python is procedural and is demonstrably good at controlling graphical user interfaces and document models.
  • Python is capable of running as a multi-threaded app or running as an event-driven program.
  • Python has fairly poor debugger support, but at least it has a few and includes language hooks to create your own debugger.
  • Python complains when something goes wrong, and is very good at telling you what went wrong.
  • Python is small, efficient and very embeddable – the interpreter is 1.2MB.
  • Python is very modular. A core set of the standard python libraries could be included at no development cost to the browser manufacturers. Additional browser-based libraries could be standardized and released independent of browser releases.

The real mistake in choosing Javascript was…

9 Responses to "Admitting that Javascript was a Mistake"

  1. I see your lips moving but I’m not hearing any words coming out of your mouth.

  2. 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.

  3. (side note: doesn’t flash also use actionscript, which is just javascript?)

  4. all the (function(){})() syntaxy boilerplate everywhere, and lack of typechecking and automatic currying certainly has me pining to write a Pure or maybe Haskell browser one of these days

    and a DSL to mash up CSS selectors with basic dom transformations and bindings – a jqueryish metalanguage

  5. “purely functional programming languages provide closure-based programming”

    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).

    “The most widely deployed functional programming language to date is Javascript.”

    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.

  6. 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.

  7. Manu wrote:“purely functional programming languages provide closure-based programming”

    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.

    Manu wrote: “The most widely deployed functional programming language to date is Javascript.”

    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)

    So, I’ve upset the 20 people that constitute the Haskell community? (*ducks*, I’m kidding, I’m kidding!)

    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

    You’re right, that’s very vague. I’ve re-phrased that sentence to read:

    “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):


    (defmacro defhtml-region (name)
    `(defun ,name (&rest args)
    (let ((attribs (and (consp (first args)) (first args)))
    (strings (if (consp (first args))
    (rest args)
    args)))
    (apply #'concatenate 'string
    (append (list (tag-begin ',name attribs))
    strings
    (list (tag-end ',name)))))))

    Do you honestly think that the Web would be better off if we asked web developers to use the above instead of a more modern scripting language?

  8. 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.

    (defmacro defhtml-region (name)
    `(defun ,name (&rest args)
    (let ((attribs (and (consp (first args)) (first args)))
    (strings (if (consp (first args))
    (rest args)
    args)))
    (apply #’concatenate ‘string
    (append (list (tag-begin ‘,name attribs))
    strings
    (list (tag-end ‘,name)))))))

    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:

    (defn new-snippet []
    (html
    (form-to [:post "/"]
    (text-area {:rows 20 :cols 73} “body”)
    [:br]
    (submit-button “Save”))))

    Which I’m sure you’ll agree is far more palatable, and possibly even shorter than equivalent Javascript.

  9. 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.