Notice:

This page has been converted from a dynamic Wordpress article to a static HTML document. As a result, some content may missing or not rendered correctly.

RE: The Pew Pew Manifesto ~ Mon, 18 Jun 2012 17:44:14 +0000

Ben Simpson made a post to Twitter a few days ago about an article that advocates avoiding writing applications directly in JavaScript. I reponded that the article is worthless, and Mr. Simpson wanted to know which points, specificially, I think are "hogwash." There a few reponses in the article's comments section that highlight my simple summary, but I'm going to attempt to go into a bit more detail here.

I have a hard time believing that the author of the article really thinks his arguments are accurate. His suggestion is to use Adobe's ActionScript language instead of JavaScript. This makes sense because he is an Adobe employee. But he did write the article, or at least attached his name to it, so let's dig into this load of bunk.

"JavaScript is not suitable for large web apps"

This is the "point" that Mr. Simpson found most interesting and the one that I think is the biggest fallacy. I would like to include a small quote from this section, but it's all so ludicrous I can't pick a single representative part to quote. The author's argument breaks down to the following points:

  1. He was asked to help work on a large internal JavaScript based project
  2. The project's source code was organized in a horrible fashion
  3. The project's code was written by people who didn't understand the language

The author then blames all three of these points on JavaScript itself. First, the project evidently contained large chunks of JavaScript in "few files." In this regard, he says that ActionScript, the language, leads the coder to using multiple files for various classes and such. You can do the same exact thing with JavaScript. Case and point: jQuery. jQuery is a large, very popular, JavaScript project. Its source code is broken down into different components with each component being defined in its own source file. These files are then "compiled" into a single JavaScript file that is "jQuery."

The primary, somewhat, valid complaint in this section is about JavaScript functions returning inconsistent data types. His example code consists of the following two functions:

  // (bad) JavaScript
  function createBunnyOrToaster(createBunny)
  {
    if( createBunny )
      return new Bunny();
    return new Toaster();
  }

  // (bad) JavaScript
  function feedBunnyOrToaster(bunnyOrToaster)
  {
    if( bunnyOrToaster instanceof Toaster )
      bunnyOrToaster.insert(new Toast());
    else
      bunnyOrToaster.feed(new Carrot());
  }

How are these functions the fault of the language? They're not. They're the fault of a programmer being stupid. What would "proper" JavaScript of this example look like? First, understand that the example assumes the coder is being lazy about creating "class" based objects. Second, recognize that createBunnyOrToaster() is the constructor for two class based objects. Thus, we would write something akin to:

  var Bunny = function(bunnyName) {
    if ( !(this instanceof Bunny) ) {
      return new Bunny();
    }

    this.name = bunnyName;
  };

  var Toaster = function(toasterModel) {
    if ( !(this instanceof Toaster) ) {
      return new Toaster();
    }

    this.model = toasterModel;
  };

With this code, the programmer can still be lazy (e.g. var myBunny = Bunny("FooFoo");), but the JavaScript isn't total garbage. John Resig has written an excellent article on this pattern.

His second example, feedBunnyOrToaster(), assumes the usage of the constructor that we just showed is ridiculous. Therefore, I will not waste any further time on it. Suffice it to say, if the code is written in a sane manner, then the constructor will always return the correct type. Thus, functions that require type inference are pointless.

"JavaScript is the browser's assembly language"

This point(?) doesn't even really deserve acknowledgement if it weren't referenced in the next couple sections. This one just dumbfounds me. I'm going to let a couple "Hello World" examples deal with this one for me. First up, vanilla x86 assembly:

  section .data
    msg db "Hello World!", 0x0a

    len equ $-msg

  section .text
    global _start

  _start:
    mov ebx, 0x01
    mov ecx, msg
    mov edx, len
    mov eax, 0x04
    int 0x80

    mov ebx, 0x00
    mov eax, 0x01
    int 0x80

JavaScript (as run in a browser):

  (function() {
    var msg = "Hello World!";
    alert(msg);
  }());

Some garbage about high level languages

I'm going to address the "Choose a high-level language for developing web apps" and "Cross-compile from a high-level language to JavaScript" points at the same time. Put simply, as I illustrated in the previous section, JavaScript is a high-level language. There is absolutey no reason to use another high-level language to write JavaScript.

Here's the thing. If you choose something like CoffeeScript, one of the more popular options that the author recommends, then your code is going to be "compiled" at least twice: first by the "high-level" language's compiler and second by the runtime's (e.g. browser's) JavaScript interpreter. When you go the route that the author suggests, then the compiler for your chosen high-level language is merely translating the code you wrote into JavaScript. As has been shown in the original article, and this article, that code may not be appropriate. Yet, that is the code that will be run by the JavaScript interpreter.

"It's optimized so it's better!"

That's the title I'm giving to the "Use Google's Closure Compiler for optimizing JavaScript" and "Optimized JavaScript is obfuscated and protects your intellectual property" points. Unless you use Closure's "advanced" option, the code returned from Closure is the exact same code as the code you wrote. The only difference is reduced white space and variable name length. The only benefit here is a smaller file size to be sent to the client. The advanced option will try to alter your code to be more efficient, but that can have serious side effects. Don't trust it implicitly as the author seems to suggest.

Along the same lines, the author equates "optimized" JavaScript with hard to read assembly or deliberately confusing code. This is utter nonsense. As I have already stated, this optimized code is nothing more than compressed code. Run the compressed code through something like JsFormat (a SublimeText 2 plugin) and you'll get code that is quite legible. Sure, the variable names won't be pretty, but the logic is still there.

"Use best practices"

The last two points, "Let your app degrade gracefully when OS features are missing" and "Invade every Web Platform!", are nothing more than the statement "use best practices" written in many more words. If the JavaScript you are writing has a chance of being run in more than one environment (Internet Explorer, Firefox, Node.js, etc.), then you should be checking to make sure the features you need are present. It's a very old concept to people writing JavaScript for the web. There's nothing special or new about these two points.

My summary

Back when JavaScript was first introduced, and people used it for really annoying garbage like snow flakes, I was one of the people who hated the language. What I was too young, or uneducated, to realize is that I hated how the language was being used (and implemented). Nowadays, it's one of the most impressive languages available. The runtimes/interpreters are phenominal, and the subtleties of the language have been exposed. So when I read FUD like the referenced article, it grates me the wrong way.

If you find yourself looking for ways to write JavaScript without writing JavaScript (see the above mentioned CoffeeScript), then you need to stop and re-think what you are doing. Take a little time to learn the language. You don't have to read JavaScript: The Definitive Guide to get a handle on the language. Familiarize yourself with the basics and then read JavaScript: The Good Parts and JavaScript Patterns. Both are short books, but they will teach you (almost) everything you need to know to write some damn fine JavaScript.

Code,  JavaScript,  Opinion,  Personal,  Technology

Comments

Ben Simpson said (2012-06-20 02:29:05 GMT):

I think it is fair to say that ActionScript is not the go-to language for web application development. I question why he and his team would port a Javascript application to such, but it sounds like a strange premise to base his opinions upon.

If I had to guess, the author's hang up about Javascript not being suitable for large web applications has its roots in its prototypical inheritance model as opposed to the classical inheritance present in other languages (including ActionScript). There isn't a right and a wrong way and each have their strengths and weaknesses. Douglas Crockford does admit to Javascript being "confused" about its prototypical nature, and trying to implement classical inheritance in Javascript he admits is misguided.

The point about an assembly language: I think you might have taken the definition too literally. What I felt he is communicating is that lots of people write in CoffeeScript, Dart, GWT, etc, and are not writing Javascript directly. They are compiling to Javascript from a "higher level language". This link continues that discussion (mostly discussing the disadvantages of this approach): http://www.kryogenix.org/days/2012/05/29/things-that-compile-to-javascript

Javascript is growing on me, but after writing a Sudoku solver without any Javascript libraries, I'm convinced you would want to extend the functionality of the data types very early in a project. (Something like Underscore.js would have done nicely) There simply isn't much to the language, but what is there I like.


James Sumners said (2012-06-22 00:24:55 GMT):

JavaScript being a prototypal language is a good thing. As an exercise, I latched on to your JavaScript Sudoku solver idea and wrote a simple project that builds arbitrarily sized Latin Squares. This project uses so called "classical" constructors, but uses the prototype to define instance methods. This reduces the time it takes to instantiate an object because the instance methods are already defined before any objects are created. Additionally, as can be seen with some of the options on the LatinSquare object, there is much greater flexibility as to what can be done with each individual object (e.g. overriding instance methods). Basically, I think it's an awesome feature of the language.

In regard to the assembly language point, I suppose I should have been clearer. I get that the author was trying to suggest that is the equivalent of machine language because other languages exist that translate to JavaScript in the end. But this assertion lends itself to the conclusion that JavaScript is not, itself, a "high-level language," but is, instead, some low level language that is so nasty no one wants to touch it except when they really, really, have to. This is a flat out absurd notion, and I still think the contrast I drew with the code samples exemplifies that.

However, I can also see how it can be construed that I am making a "GET OFF MY LAWN!" argument. It's very likely that pre-processors like CoffeeScript generate better JavaScript than I, and most people, can write directly in a lot of, if not most, situations. But I fail to see how writing in a scripting language that "compiles" to another scripting language is better than writing directly in the target scripting language. The notion even makes that previous sentence silly.

Finally, I'm not sure what you think is missing from the language itself. The standard objects have all of the necessities for writing complex applications. And the standard library (standard objects) is expanding quite a bit in ES6. You'll have to provide an example or two of what you mean.