Closures considered harmful

Before you start throwing things this way, hear me out. A few years ago, no one ever talked about closures in JavaScript. They were a footnote to JavaScript, mostly discussed by people like Douglas Crockford on the Web. Since Ajax has become the focus of everyone’s life, closures have been talked about more and more, leading to some very powerful JavaScript solutions. The problem here is maintainability.

The more closures you use in your code, the more difficult it becomes for other people to understand it, and the more memory you use (let’s not even talk about the infamous Internet Explorer memory leaks). Take a look at some hardcore closure examples and see how long it takes for you to track down which variable is declared where and how it is used.

In my opinion, there’s only a handful of times when closures should be used. If you are using closures to hide variables or create “private” and “priveleged” methods, then you are writing unmaintainable code. The simple fact is that private variables are not a necessity in JavaScript. If you are building an API, your public methods are the ones you document; your private methods are the ones you don’t. Unlike compiled languages, anyone can go into your code at any time and figure out exactly what it’s doing, so why bother trying to hide properties and methods from other developers?

If you are writing JavaScript code for a company, you have a duty to make sure your code is maintainable and scalable long after you are gone. You do this by avoiding closures and making your objects and their relationships very clear. You may think you’re being smart using closures, but all you’re doing is making the code unnecessarily complicated and that much more difficult to understand. Closures are akin to misdirection in magic: you make people look in one direction while pulling a quarter from behind their ear. It’s cute, and sometimes brilliant, but there is no value when your main goal isn’t trickery.

So I implore all JavaScript developers working for various companies around the world, do yourself and your coworkers a favor: next time you think about using closures to alter scope or change the visibility of a property/method…don’t

Comments

  1. Julian Turner

    As an amateur, I don't use closures to hide properties and methods.

    I do find uses for them for the following purposes:-

    (a) Implementing call-backs.

    (b) Passing a function to an iterator. The function may contain a closed variable, to be updated when that function is called by the iterator for each member of a collection.

    (c) I have developed a mad but fun module system for my libraries of functions. The source script for each module that is imported is "eval'd" (yes, you read that correctly, "eval'd") within the last module imported (through a special closure() function that each module provides), giving each successive imported module access to the variables and declared functions of all previous modules up the scope chain, and thereby saving "this.that.theother()" verbosity for cross-module calls (although that is still an available alternative). I know scope chain look-ups are much more expensive, but it does seem to work without a noticable performance hit accross IE, Firefox and Opera, and I prefer the benefits of being able to use names without having to be explicit about the module they belong to (my naming conventions/module structure make it obvious). You can also then implement your application code as a further module, and make it the last module you import, giving it closure access to all library modules. Mindboggling (so probably not maintainable for that reason alone), but the result is actually quite tidy.

  2. Dustin Diaz

    Nicholas, I disagree. Using closures for block scope is in fact the greatest uses for them. I don't necessarily think it's all that hard to read - and even if it was, I don't think that's reason enough to avoid them.

    I did notice that you mentioned it was "your opinion," but I find it hard to believe that using a closure for creating private and privileged properties and methods makes code unmaintainable. How so? I would think that it keeps it more manageable because your code can then be broken up into modules. Eg: module pattern.

    var module = function() {
    var my_module_property = 'foo';
    return {
    public : function() { }
    };
    };

    Also stating that "private vars are not a necessity" is a fact... yeah, ok; so? "so why bother trying to hide properties and methods from other developers?" Because that's the "professional" way ;)

    Don't mean to nitpick - but it seems as though the way you've written your thoughts on the matter, I figure the opposite side should at the least be well represented and that people who do practice these other methods (those of us who "think we're smart") are not in fact stupid.

    To say the least, I don't buy your arguments.

    Cheers.

  3. Nicholas C. Zakas

    Dustin - you're entitled to your own opinion, of course. I stand by my statements. In my experience, the more closures in code, the harder it is to read, debug, and maintain. Your argument that block scopes are the "greatest" way to use closures doesn't seem to be backed up by any proof. Why use more memory to do the same thing that can be done with less?

    And the "professional" way is what you make of it. I say the the professional way is to make your code make sense so that if you get hit by a bus, someone else can pick it up and figure out what was going on. I would put any file that doesn't use closures up against a similar one that does, and I'm confident that you (and everyone else) would be able to decipher the former faster than the latter.

    All that being said, I recognize that it's impossible to convert someone with strong opinions. However, if you're basing your argument on "because it's cool" or "because it's possible", I would encourage you to come back with some logicaj arguments supporting your assertions.

  4. Dustin Diaz

    Hi Nicholas,
    I forgot to come back and revisit - I was looking forward to your response. To make it fair, sure - closures are not always needed, and I don't necessarily have a strong opinion about it, but just a more or less sensible one.

    Hiding private information can have two benefits. One being that your module or object, or function block (which contains scope) will not conflict with any other, and they can't accidentally be called by any other outside the module. Even using a closure to hide your app will do the trick:

    var Public = {};
    (function(){
    var keep_hidden = function() {

    };
    Public.expanded = 'foo';
    })();

    In the end, function blocks are the only things in JavaScript that give us scope (with the exception of 'let' blocks in JS 1.7)

    I suppose in one sense I came off like I meant that one should use a closure for everything. No, definitely not. And I will admit, the syntax can look funny sometimes.

    If I were to reword your statement about "the more closures in your code, the harder it is to read" to something more along the lines of "the more 'nested' closures in your code, the harder it is to read." - and I think we can both agree on that.

  5. Nicholas C. Zakas

    Dustin - I can accept your rewording. Nested closures are horrid things that should be avoided whenever possible. I still don't think that closures for private variables/functions are necessary. If you're worried about collisions, namespaces can be used to ensure uniqueness. I always hear the words of Brendan Eich whenever people talk about private methods in JavaScript: it can use around three times as much memory. To me, the tradeoff isn't worth it.

Understanding JavaScript Promises E-book Cover

Demystify JavaScript promises with the e-book that explains not just concepts, but also real-world uses of promises.

Download the Free E-book!

The community edition of Understanding JavaScript Promises is a free download that arrives in minutes.