Skip directly to content

Why so many of us hate JavaScript

on October 18, 2010 - 6:31pm

I know some really smart Drupal developers who hate JavaScript. Maybe you're one of them. Here's a little quiz: You read in the Drupal 7 module upgrade guide that all D7 JavaScript code should be wrapped as follows:

(function ($) {
  // Original JavaScript code goes here 

What is your reaction?

a) Nice! A self-executing function that's closed over the free variable $ at execution time.
b) Oh right, that clever-looking jQuery pattern that I've seen all over but don't understand because I can't Google it.
c) What the freak is that? I guess I'll copy and paste it even though it makes no sense. I hate JavaScript.

If you answered c), you're in really good company. I gave a talk called "JavaScript Demystified" at the Pacific Northwest Drupal Summit in Vancouver a couple of weeks ago, where I talked about why JavaScript is so confusing to PHP developers, and how we can write it differently. There's more to talk about than I could fit in one hour, so I'm starting a mini-blog on this site where I can blather at length.

During the talk (slides available here), I spent most of the hour fulminating against closures. Wikipedia helpfully informs us that a closure is "a first-class function with free variables that are bound in the lexical environment." That is total gibberish to people who haven't studied functional programming. In case you're in that category, here's a quick explanation: functional programming is what you do when you're writing Lisp, or Erlang, or Haskell. In these languages, the functions you write are just like the mathematical functions you studied in algebra class - all that ƒ(x) = 2x business. It's a totally different way of programming, with its own set of tradeoffs, which Larry Garfield explained really well in a recent blog post that I recommend to anyone who wishes they'd taken CS in college.

One reason JavaScript is so confusing is that you can write it in a functional style, using closures. In fact, most of the JavaScript you'll find in the wild is full of closures. Here's an example of one:

Drupal.behaviors.myModule.attach = function (context, settings) {
  // This is a simplified example, so Drupal experts, please overlook the blatant omission of $.once and context.

  var message, hideMessage;

  // Find where the message is on the page.
  message = $('div.messages');

  // Define a function for hiding the message.
  hideMessage = function () {
    message.css('display', 'none'); // <-- We just used a variable we didn't define inside our function!

  // Hide the message (in real life, we wouldn't call this until someone hit the close button, or whatever).

See how the message variable was defined outside the hideMessage() function? That's what makes hideMessage() a closure: it uses a variable that got defined in its parent function. And if you're going in to fix a bug in hideMessage(), you have to know all about the message variable: where was it defined? What is its value when hideMessage() gets called? Is there code further down the page that sets message = $('#some-other-div-entirely')?

This is a really simple example, so it's not hard to follow what's going on. But add in a whole bunch more variables, and start writing functions within functions within functions that use variables defined in their parent function and their grandparent function, and unless you're an experienced functional programmer, you have the recipe for a big pile of spaghetti code. Even worse, it's spaghetti code that you can't understand unless you know what closures are and how they work.

The good news is that you don't have to learn Lisp to write good JavaScript. There are ways to avoid writing closures, and to limit the scope of the closures you absolutely have to write, so that people can understand your code even if they don't write JavaScript books for a living. The example code from my presentation demonstrates some of the ways you can do that, and I'll expand on those examples in a future post if anyone's interested.

By the way, my answer to the quiz question is

d) Don't bother wrapping your JavaScript in that crazy closure at all. Just stick var $ = jQuery; at the top of any function where you want to use $. Life is too short.


James O&#039;Beirne's picture

If you find closures or anonymous functions opaque, maybe you shouldn't be getting paid to write JavaScript. Honestly, which is better for readability? It should take about fifteen seconds to explain/understand self-executing, anonymous functions used for scoping.

Josh Caldwell's picture

By placing $ = jQuery at the top of your function you're actually creating a situation where window.$ = jQuery ... (var $ = jQuery; would work) ... additionally, part of the point is to create a closure in which the functions that you define, variables, ect, will not conflict with other modules functions and variables, you're bypassing that ... and thus defeating the whole purpose and causing possibly namespacing issues.'s picture

Hi, I do think this is a great site. I stumbledupon it ;) I will come back once again since i have bookmarked it.
Money and freedom is the best way to change, may you be rich and continue to help other people.

arvonlisäveroprosentti 2014's picture

This piece of writing offers clear idea for the new visitors of blogging, that genuinely how to do running a blog.

Erik Reppen's picture

You've misunderstood the one up top. It's just a lazy way to define an anonymous function and fire it while avoiding pollution of the global namespace.

function(){}//a completely useless function definition
var x = function(){}; x();//assigned to a var (causing evaluation) and fired

function(){}(); //but you can't just fire it like that. It's not evaluated
//until after that statement is closed (the semi).

These work because the operators force evaluation of the funcs:
+function(){ alert('bob'); }()
!function(){ alert('bob'); }()

Paren style is generally preferred because forgetting a semi could cause something extra-stupid to happen in the above examples and parens are commonly used to force evaluation.

So, what you have up top there:

function($){} //a function definition defining $ as a parameter name

// that func defined, evaluated with parens, and fired with jQuery passed in to
//the $ param - it's just a lazy way to do it all in a one-liner

The whole point by the way is to assign jQuery to a local context of the function so you're not bouncing up and down the call object chain every time you reference jQuery. They also use this in the JQ factory definition to bring window down to a local reference so it can be minimized.

People tend to confuse what I call anonymous auto-invoking functions (self-invoking is a bit of a misnomer) with closures because they are frequently used in examples of how to resolve closure issues. A good example of a closure shows a var's value getting locked into place because what closures really are is the binding of execution context to function definition as the function scope closes.

//the problem - all these funcs alert 0
//Why? Because you call that func when the loop is done and i is 0 at that point
var i = 8,
arrayOFuncs = [];
arrayOFuncs[i] = function(){ alert(i); }

//The solution - lock execution context down by completing a function call.
//Scope closes but the func holds the var value as it was when the scope closed.

var i = 8,
arrayOFuncs = [];
//function defines and completes - i would be out of scope without closures
arrayOfFuncs[i] = (function(){
return function(){ alert(i); }

//Now you should get different vals for each array element func fired
//e.g arrayOfFuncs[3]; //'3'

It has taken me a few 'aha!'s to get here. So let me re-describe. If a language does not have closures, when a function is done, everything inside is tossed out, garbage-collected, meaningless. Without closures, you cannot have very interesting first-class functions (funcs passed as params). But the important thing to understand above:

In the all-alerts are '0' example, you can still see i because of JS-scoping. It's okay for JS funcs to see what's in outer-contexts. This may be closure-related actually but I'm not going to pretend I fully grok that.

In the all alerts are <i at time of definition> example, 'i' is locked down because the outer function finished, tried to garbage collect but saw that a function that could be fired by anything else later was referencing 'i'. So that func gets to have a local var 'i' to reference that is locked down at the value of the outer-i that the outer function "closed" on. The concept of "closure" is execution context getting locked down when we find a way to make it possible for vars inside a function to be referenced after it's supposedly finished doing what it was doing.

Don't feel bad, I've had guys at a Netflix interview tell me (function(){})() is a closure. It's not, really. Evidence of closures being likely, yes. But not a good example of a closure.

Also, free yourself from Drupal. Trust me on this one.

free small woodworking projects's picture

It is a sourcebook for remodeling ideas and
products. The back arm should also form a letter "L", with
the elbow facing down. Hannah and Elijah match one another so much because they feed off of one another's toxic narcissism.

how to plan my first baby shower's picture

An impressive share! I have just forwarded this onto a co-worker who had been conducting
a little homework on this. And he actually ordered me breakfast because I discovered it for him...
lol. So allow me to reword this.... Thanks for the meal!!

But yeah, thanks for spending some time to discuss this issue here on your site.

money making apps on ipod's picture

Everything posted made a lot of sense. However, what
about this? suppose you typed a catchier
title? I am not saying your content is not
good, however suppose you added a headline that makes people desire more?
I mean Add new comment | JavaScript Demystified is a little vanilla.
You could peek at Yahoo's home page and note how they
create post headlines to grab viewers to open the links. You
might add a related video or a related pic or two to get people
excited about what you've got to say. Just my opinion, it
might make your website a little livelier.

Jason's picture

Why are most Javascript code snippets displayed in black and white on most articles that you come across? This enhances the view that javascript is ugly as without colour coding your mind needs to exert extra effort to separate the various blocks and meanings. Any other language and its usually grey for comments, blue or black for language statements and green for strings, but Javascript seems to be predominantly written using notepad, or at least most of the code listings you come across seem to be like this. I think if you use a proper editor to write Javascript, it becomes a lot more easier to follow the code and bring it more on level with other programming languages.

Post new comment