The Initializer Pattern 7

If you haven’t read my previous tutorial on Objects and The Prototype Chain, it would be a good idea to do so. This article builds on the concepts presented there. Object oriented programming with only those concepts, while possible, can get pretty verbose, so we often use common abstraction techniques – called Design Patterns – to simplify the task.

The Initializer Pattern is my favorite OO design pattern in JavaScript. I find it intuitive and easy to use. It’s straightforward, and contains all the necessary internal knowledge of an object in the object itself. I’ll get to each of these points as we go along, but for now, let’s just take a look at the most basic concept of the pattern: an initialization function.

In Comparison

In the first article, using basic prototypal features, we see code that looks like this:

var point = {
    translate: function(x, y) {
        this.x += x;
        this.y += y;
    }
};

var obj = Object.create(point);
obj.x = 42;
obj.y = 17;

obj.translate(7, 9);

Simple and straightforward, but a little verbose (especially with larger amounts of initial values), and the responsibility of assigning values lies outside the object itself. Let’s see what happens with an initialization function, though:

var point = {
    init: function(x, y) {
        this.x = x;
        this.y = y;
    },
    translate: function(x, y) {
        this.x += x;
        this.y += y;
    }
};

var obj = Object.create(point);
obj.init(4, 5);
obj.translate(7, 9);

What’s Good?

First, the object itself maintains control over what happens to the data is used. Sure, all its properties are still public and mutable, but a point determines how to interpret and initialize the values passed into the intitialization function. It can set defaults if the values are undefined, and it can massage the data into a proper format.

Even more importantly, it does all of this in one place. If the way we treat the data needs to change, it will necessarily change for all of our points. This drastically affects the DRYness of our the code. This is not a feature unique to the Initializer Pattern; It is (or should be) common to all good design patterns. But it is a benefit nonetheless.

This pattern also keeps inheritance simple and DRY.

Inheritance

Let’s extend our point object into a 3D point and see what happens:

var point = {
        init: function(x, y) {
            this.x = x,
            this.y = y
        },
        translate: function(x, y) {
            this.x += x;
            this.y += y;
        }
    };

var point3d = Object.create(point);

point3d.init = function(x, y, z)
{
    point.init.call(this, x, y);
    this.z = z;
}

point3d.translate = function(x, y, z)
{
    point.translate.call(this, x, y);
    this.z += z;
}

var obj = Object.create(point3d);
obj.init(42, 17, 29);
obj.translate(7, 9, 12);

First, initialization code is encapsulated inside the objects that care about it. This point has already been covered, but the granularity extends to inherited objects themselves. A 3D point is really just a 2D point with an extra dimension, and that’s how it’s logically represented in this structure. The first two dimensions are the responsibility of point (as it should be).

Next, with no extra code, and no duplicated code, all necessary data is stored on the object itself. If you take a look at the prototype chain, you’ll see that the prototype of obj (point3d) has only functions, and the prototype of the prototype of obj (point) also has only functions. This prevents the possibility of accidentally sharing data between objects inheriting from the same prototype. As long as you stick to the pattern, this.x will always refer to the right value. This is a benefit over other patterns, as well as a benefit over the base method of OOP in JavaScript.

This is a very simple constructor, though. Maybe we want to increase the complexity a little, and add some default values.

var point = {
        init: function(x, y) {
            if (typeof x === 'undefined' || x === null) {
                this.x = 0;
            } else {
                this.x = x,
            }

            if (typeof y === 'undefined' || y === null) {
                this.y = 0;
            } else {
                this.y = y,
            }
        },
        translate: function(x, y) {
            this.x += x;
            this.y += y;
        }
    };

var point3d = Object.create(point);

point3d.init = function(x, y, z)
{
    point.init.call(this, x, y);

    if (typeof z === 'undefined' || z === null) {
        this.z = 0;
    } else {
        this.z = z;
    }
}

point3d.translate = function(x, y, z)
{
    point.translate.call(this, x, y);
    this.z += z;
}

var obj = Object.create(point3d);
obj.init(42, 17, 29);
obj.translate(7, 9, 12);

At this point, the code reuse possibilities should become clearer. The amount of code is growing, but it’s organized in such a way that it’s still maintainable. Each object handles the data it needs to handle – nothing more, and nothing less.

Some Final Notes

The initialization function can obviously be named anything you want. I usually stick to init for a couple reasons:

  • It provides a uniform interface for object setup. If you’re working with my code, you can probably call init to initialize my object, and if it doesn’t have one, then it doesn’t need to be initialized. If you want to use something more semantic in a particular case, it’s okay, but uniform interfaces are a good idea.
  • The abbreviation leaves off the annoying international spelling issues. As you may have noticed, I’ve been using the American English spelling (-ize) throughout this article, but the UK English spelling is initialise (-ise). Leaving it off entirely circumvents the issue.
  • I don’t know how popular this pattern is. I really have no idea if anybody else uses it. But it hasn’t done me wrong since I’ve been using it in the way presented, and I see very little reason why I would switch from it.

And there it is. The Initializer Pattern, in all its glory. Go make some stuff.

About Me

I wear several hats, and I do a lot of different things. By day, I’m a mild-mannered web developer for McKissock Education. By night, I’m CTO and Lead Developer of SlickText.com – Text Message Marketing service. I’m also a musician, songwriter, dancer, and pretty cool guy.

January 21st, 2013 by

7 thoughts on “The Initializer Pattern

  1. Reply Ryan Jan 30, 2013 11:25 am

    Thanks for the clear explanation and examples. I have been using pseudo-classical style with prototypes, but I hate having to do any inheritance at all with that pattern–it’s confusing and verbose. I like this pattern a lot. I think I might be tempted to capitalize the first later of my object (i.e. Point instead of point) just so I can see that this is a data structure I’m using to build new objects. That makes sense to me since I wouldn’t normally use the point object directly. (But maybe this is just the classical programmer in me speaking.)

    (Your examples have “this.y = x” and “this.z = x”; you probably meant to set those to y and z respectively.)

    • Reply Ryan Kinal Jan 30, 2013 1:03 pm

      Yeah, I’m definitely tempted to capitalize too. It seems slightly incorrect to me, as any object can technically be used with Object.create, but it might be a good indicator of intention.

  2. Reply Erik Jan 30, 2013 11:48 am

    There seem to be a couple mistakes in your code snippet.

    In the second code block of your comparison, you fail to use the `init` function that you created, instead you set obj.x and obj.y directly.

    In both of your inheritance examples, you use `point.translate.call` but fail to supply a new calling context.

    That being said, the only reason I can notice these mistakes is because of how clearly you’ve elucidated how objects and prototypes work in the Objects and the Prototype Chain article and in The Illusion of Class article.

    Thanks for these great posts.

    • Reply Ryan Kinal Jan 30, 2013 12:59 pm

      Thanks for the feedback! I think I need some better proofreaders ;-)

      I’m glad you’ve enjoyed these posts. I’ve certainly enjoyed writing them, and have clarified my own knowledge of the language in the process.

  3. Reply Nicolas Froidure Feb 1, 2013 4:23 pm

    Hi,

    Why don’t you use a constructor to intialize you’re values ? Something like that :
    var point = function function(x, y) {
    this.x = x;
    this.y = y;
    }};
    point.prototype.translate = function(x, y) {
    this.x += x;
    this.y += y;
    };

    var obj = new point(0,1);

    obj.translate(7, 9);

  4. Reply Hughes Apr 10, 2013 10:23 pm

    I have recently started a web site, the information you offer on this web site has helped me tremendously. Thank you for all of your time & work.

Leave a Reply