The Factory Pattern in JavaScript

We could also call this article, “JavaScript Constructors Considered Harmful.”

I recall reading a post recently which describes factory methods as a best practice. I can’t tell you how thrilled this made me as I’ve been advocating this for years, even to the extreme view that the author used as an example: new Form().

In my most recent talk at AJAXWorld 2009, I briefly discussed the Factory Pattern as it applies to JavaScript. In my talk, I took a jump away from simple best practices and gave a real-world problem/solution approach to factories in JavaScript.

The problem: JavaScript will allow you to invoke constructor functions as normal functions.
The simplest possible solution: Use a factory method to instantiate everything.

My personal recommendation is to only use constructors internally and to never expose constructors directly.

What the hell? Why are constructors so bad?

Constructors in JavaScript are bad because of one thing, and it’s the same thing that is at the heart of almost all of JavaScript’s problems: implied global scope.

Consider the following code:

// Define our constructor function
var Person = function (name, location) {
    this.name = name;
    this.location = location;
};

// Create one instance of Person
var mike = new Person('Mike G.', 'NYC');

// Create another instance of Person
var alex = Person('Alex H.', 'NYC');

Did you spot my mistake? I omitted the new keyword while creating the second Person instance. If you run this code in any web browser, you’ll notice that the browser will redirect you immediately upon running it.

This is a big problem.

When you invoke any function with the new keyword, it treats it as a constructor and executes within the context of the newly created instance. When you invoke any function without the new keyword, it treats it as a normal function and executes within the context in which the function was defined (typically window).

With that knowledge, go back and re-read the code and tell me why the browser redirects now…

Factories save the day

The easiest way to fix this problem is to use a factory. Here’s my proposed solution:

var Person = function (name, location) {
    return (this === window)
        ? Person.factory(name, location)
        : Person.factory(name, location, this);
};

Person.factory = function (name, location, instance) {
    instance = instance || new Person;
    instance.name = name;
    instance.location = location;

    return instance;
};

One of JavaScript’s brilliant features is that Constructors can have return values. In this example, my constructor is returning the result of the Person.factory. It is Person.factory’s job to always return a proper instance and set it up properly.

Now it doesn’t matter how you invoke this constructor. You can use new or you can omit it. This is defensive code and it’s JavaScript done right.

Update: 2010-01-21 — One can also hide the constructor entirely.

var Person = (function () {
    var Person = function (name, location) {
        this.name = name;
        this.location = location;
    };

    return function (name, location) {
        return new Person(name, location);
    }
})();
This entry was posted in Code, Design Patterns, JavaScript, Uncategorized. Bookmark the permalink.

8 Responses to The Factory Pattern in JavaScript

  1. Mike says:

    I don’t see how your proposed solution is supposed to work. Could you double-check your code? Thanks.

    • mikeg says:

      @Mike: You’re absolutely right. Good eye. I’ve updated the code and it should work fine now. Thanks for catching that.

  2. Daniel says:

    Mike, this is a good use of the factory. On the other hand, since ‘new’ is a KEYword, a programmer could just already know what they are doing, and thus not forget it. Hows self employment going anyways?

    Daniel

    • mikeg says:

      @Daniel: You right, programmers should know to use the new keyword, but look around the net. How many JS tutorials have you seen where people create arrays like:

      var myArray = Array(1,2,3);

      It’s hard to say that programmers will know to use JS constructors properly too. Unless you know my naming convention or I document my code appropriately, can you spot my constructor?

      var Group = function () { /* … */ };
      var group = function () { /* … */ };

      Since JS uses functions as its constructors, it makes it really difficult to discern simple functions from constructors. Furthermore, the language offers no protection against calling constructors incorrectly: it simply masks your errors and you must be JS-savvy enough to know where your problems are. Imagine how hard it would be to debug the first example if your browser keeps redirecting on you!

      • Maik K says:

        But I guess the “= Array( x, y)” is more a Problem of switching between different languages. E.g. take PHP – where you initialize an array like this ;)

  3. Pingback: Mojo Lists: Restructuring our Code (Part 3) « WebOS Boston

  4. Your second example is interesting but I fear it might add extra complexity that would be harder for a newbie to debug than forgetting the ‘new’ keyword. How about something like this:

    function Person(){
    if(!(this instanceof Person)){
    throw “You forgot to use ‘new’”;
    }
    }

    – Or –

    function Person(){
    if( !(this instanceof Person) ){
    return new Person();
    }
    }

  5. Seems like it would be more dangerous to hide the programmers errors from them.

    Something similar I wrote about a while ago:
    http://www.fijiwebdesign.com/blog/single-global-javascript-object-namespace.html

    Didn’t realize it was the factory pattern then.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>