Media Temple Hosting

My Current JavaScript Design Pattern

With every major JavaScript project, I’ve tried something new, improving on what I’ve written before. Currently, whenever I build something from scratch, I use a variation of what Addy Osmani and others commony refer to as the module pattern.

Here is my version below, which assumes jQuery, and then I’ll provide some explanation of what’s going on here and how I use it:

var s,
    PrimaryNameSpace = {

        settings : {
            basicExample: $('.main'),
            nestedExample : {
                first: true,
                second: true,
                third: true,
                fourth: true,
                fifth : ['one', 'two', 'three', 'four', 'five', 'six']
            },

            foo: 'bar'

        },

        init: function () {
            s = this.settings;
           
            this.nextMethod();
            this.anotherMethod();
        },

        nextMethod: function () {
        },

        anotherMethod: function () {
        }

    };

$(function () {
    PrimaryNameSpace.init();
});

Let’s look at how this is structured, and why I find this easy to work with.

The main part of the code is enclosed in its own object, creating a namespace. Inside of that primary namespace are defined methods, along with a group of “settings”. Let’s start with the settings.

The settings Object

The settings object is where I place any cached objects and values that I intend to reuse throughout the pattern. Some settings are not cachable because their value will change depending on what happens later, so for those I’ll just initiate them with a value of “null”.

In order to access the settings object from within the init method, I need to use this.settings. So in this above example, if I want to access the first cached object, I would have to do something like:

console.log(this.settings.basicExample);

But that’s a little convoluted. Instead, as you can see, I’ve cached the settings into a variable “s”. This way, I can access all of my settings as properties of the “s” object.

As shown in the example code, a single settings value can itself be a nested object of values. Once cached as “s”, the nested example would be accessed using s.nestedExample.second.

I should admit that for the longest time I assumed that the “s” object had to be reset inside of each method. But, as someone rightly pointed out, it only has to be declared once in the first method, since all methods have access to the parent closure. (Update: Made a small correction as pointed out by Rey Bango; the “s” variable needs to be declared outside the individual methods, so we don’t have to make it global, and so it will be accessible anywhere.)

The init Method

The first method is the init method. This can be used to “initialize” the app, doing a lot of generic type gruntwork that doesn’t yet get into specifics on how the user might be interacting with the interface, or other more specialized behaviours.

The init method will also be the first one that’s triggered (which you can see happening at the bottom). Once the init method is fired, then the others can be fired too.

If the other methods are not dependent on anything that happens within init then I can just fire those outside the parent closure, as I do with init. Otherwise, in case I’m passing values from init to the other methods, it will be best to trigger those from within that first method.

Specialized Methods

The methods that follow init will generally be very specialized. For example, if I’m manipulating the URL’s hash (if it exists), then I might call a method called getHash or doHash (insert substance abuse joke here).

So anything that I can define as doing a single specific thing, or as Chris Coyier says “one chunk of functionality”, I’ll define that as a separate method. (And as a side point here, Chris’s article was definitely the inspiration for me to write this post, even though I’ve been planning to write this for some time now.)

Calling Methods Inside Methods

Every method can be called, from anywhere, using the syntax PrimaryNameSpace.nextMethod(). But when calling a method from inside another method, I can simply use this.nextMethod().

The only variation is if I create a new context inside of a method. In the context of a method, “this” is a reference to the parent object. But if (for example) inside of a method I use a jQuery feature that allows an anonymous callback function, then the value of “this” changes inside the anonymous callback. So if I was calling one of my methods in that anonymous function, I’d have to use the full syntax PrimaryNameSpace.nextMethod().

Feedback is Welcome

For most experienced JavaScript developers, this stuff is probably pretty basic. But I don’t claim to be a JavaScript expert. In fact, there are some areas of JavaScript that I’m extremely uncomfortable with. So take everything here with a grain of salt, and if you think there’s anything I’ve said that’s technically inaccurate, or if you think there’s something about this pattern that could improve, I’m glad to hear it.

And feel free to share any JavaScript patterns that you’ve personally become more comfortable using.

Update:

A good point is brought out by Joseph Silber for those concerned about the “s” variable being declared outside the namespace. With the whole thing inside a self-invoking anonymous function, you can keep things localized.

Also, Chris Coyier has posted something further on this: How Do You Structure JavaScript? The Module Pattern Edition.

22 Responses

  1. Tom:

    I’ve been there :-) I’ve moved away from this pattern towards the pubsub based modular pattern. e.g.:

    
    (function ($, App, window) {
      'use strict';
      var ready = false,
    
      handler = function (e) {
      },
    
      init = function (page) {
        if (ready) return;
        // init stuff
        $('.el').on('click', handler);
        ready = true;
      };
    
      App.Subscribe('app/ready', init);
    }(jQuery, App, this));
    

    It’s much more flexible, you can use handlers on events without using “this”, everything looks much cleaner and modules are abstract and invisible to the DOM.
    If needed – I can still assign a var to the module and return some API.

  2. I prefer function rather the object as main “namespace”. My aproach is quite similar thought:

    
    /**
     * @name someFunction
     * @author kfb
     *
     * Basic usage:
     * var someFunction = new SomeFunction();
     * someFunction.init();
     *
     * additionally you can use methods like someFunction.methodName();
     *
     * Advanced usage:
     * var someFunction = new SomeFunction({
     *      "additionalOption": "thatCanOvervriteDefaults"
     * });
     */
    function SomeFunction(opts) {
        var _cfg;
        var _root;
    
        //defining defaults and extending/overwriting it with inputted parameters
        this.config = $.extend({
            "someOption":       "some value"
        }, opts);
    
        /*
            INITIALIZE
        */
        this.init = function() {
            //assign _root and config variables
            _root = this;
            _cfg = this.config;
    
            //some code
        }
        /*
            Some Private Method (no "this")
        */
        _somePrivateMethod = function() {
            //some code
        }
        /*
            Some Method
        */
        this.someMethod = function() {
            //some code
        }
    }
    
    //declaration and auto initialization of someFunction
    var someFunction = new SomeFunction();
    someFunction.init();
    
  3. I also like

    
    var someFunction = new SomeFunction();
    

    aproach – thanks to it you can make many instances based on constructos (function that starts with big letter).

    Of course you can resign from constuctor and treat it as only one instance:

    
    /**
     * @name someFunction
     * @author kfb
     *
     * Basic usage:
     * someFunction();
     *
     * additionally you can use methods like someFunction.methodName();
     *
     * Advanced usage:
     * someFunction({
     *      "additionalOption": "thatCanOvervriteDefaults"
     * });
     */
    function someFunction(opts) {
        var _cfg;
        var _root;
    
        //defining defaults and extending/overwriting it with inputted parameters
        this.config = $.extend({
            "someOption":       "some value"
        }, opts);
    
        /*
            INITIALIZE
        */
        this.init = function() {
            //assign _root and config variables
            _root = this;
            _cfg = this.config;
    
            //some code
        }
        /*
            Some Private Method (no "this")
        */
        _somePrivateMethod = function() {
            //some code
        }
        /*
            Some Method
        */
        this.someMethod = function() {
            //some code
        }
    
        /**
         * AUTO INIT
         */
        _root.init();
    }
    
    //declaration and initialization of someFunction
    someFunction();
    
  4. Hey Lou,

    I think your code may be off. The “s” var declaration you did will only be visible to the init method, not the rest. Check out the fiddle I created:

    http://jsfiddle.net/M8E7t/1/

    In looking at the comment you referred, your reply showed how you had the “var s” declaration up higher.

    • Yes, corrected. I tested it myself and it was working the way I had it. Now I realize, in my test inside the “init” function, I must have left off the “var” statement, making “s” global.

      Thanks, I’ll add a note clarifying.

  5. Maciej Baron:

    Your solution is fairly okay, it’s just a simple JSON-structured approach, however you do not allow for public and private attributes/methods, and also ignore other potential issues. Here’s my solution using an anonymous self-executing function:

    
    (function ($, MyObject, undefined) {
      MyObject.publicFunction = function() {
          console.log("This is a public function!");
      };
      var privateFunction = function() {
        console.log("This is a private function!");
      };
      
      MyObject.sayStuff = function() {
        this.publicFunction();
        privateFunction();
        privateNumber++;
        console.log(privateNumber);
      };
      var privateNumber = 0;
    }(jQuery, window.MyObject = window.MyObject || {}));
    
    MyObject.sayStuff();
    MyObject.sayStuff();
    MyObject.publicFunction();
    MyObject.privateFunction(); // Returns error
    privateFunction(); // Returns error
    

    (apologies if it's not well formatted, it's not my fault)

    MyObject here is your namespace. As you can see, this way I can have private and public attributes in my namespace, which can come in handy.

    Let me also explain other things. If you want to make your code as accessible and reusable as possible, you need to get rid of assumptions. If you need jQuery, that's fine, but don't assume that you can access is using $. That's why it's better to pass jQuery, and then assign it to $ in your scope. Secondly, you don't want to overwrite your namespace - that's why we use window.MyObject = window.MyObject || {}, which will return MyObject if it already exists, so we can expand it - see the huge advantage here? Finally we have undefined. You may wonder why the heck do we need to put it there? Well, in older versions of ECMAScript you were able to redefine undefined. If provide our function with two parameters, and we define the third one as undefined, we will be absolutely sure that undefined is, well, undefined.

    You can use your JSON-structured approach to define all the public attributes and functions though.

    I hope this helps.

    • Awesome suggestions, Maciej. Will definitely look more into this. Thanks!

    • This is the same approach I use. The concept of passing in the namespaced object in a self executing function I find to be very elegant. You can even repeat the pattern to further nest your namespaces.

      
      (function ($, MyObject, undefined) {
      
          ...
      
          MyObject.nestedNamespace = MyObject.nestedNamespace || {};
      
          //add a public function to our new namespace
       
          MyObject.nestedNamespace.logNestedMessage = function () {
          
             console.log("A clever message");
      
          };
      }(jQuery, window.MyObject = window.MyObject || {}));
      
      
  6. Oliver Lassen:

    As http://css-tricks.com/treehouse-ad/#comment-251356 pointed out, you should put your code in a self execution function so you don’t pollute the the global.

  7. couple of things to help you, I tend to use this:

    
    ...all of your stuff...
    
    myMethod:function(){
         var me = this;
    
         return me;
    },   //end myMethod()
    
    

    By declaring me = this; I have:
    a) saved myself a few bytes when I minimize the code (as “this” is a reserved word in JavaScript)
    b) able to keep track of the correct context of “this” through closures

    By returning me I am able to chain methods outside like jQuery.

    I tend to over comment my code, which I happen to like, this way I know where braces end, where functions end, and stuff. I know modern IDEs can help you, but it’s still nice to have the comment so I can see at a glance without having to move my mouse/cursor to get the IDE to match the brace.

    Example of using me:

    
    
    clickOnTags:function(){
         var me = this;
    
         $("a").on("click",function(e){
              //this now reffers to the a tag we're on, but me still reffers to our PrimaryNameSpace object
              me.somethingElseOnTheObj()
         });
         return me;
    },   //end clickOnTags()
    
    
    

    One last thing you can look at is jQuery’s $.proxy. This allows you to keep scope of “this” when calling functions:

    
    
    myMethod:function(){
         var me = this;
         $("a").on("click",$.proxy(me,"clickOnTags");
    
         return me;
    },   //end myMethod()
    
    //Since this function isn't meant to be called directly, do not return me anymore
    clickOnTags:function(e){
         var me = this;
    
         //Do something when you click on the tags
    },   //end clickOnTags()
    
    
    

    Just m y two cents.

  8. Gummibearlab:

    The article is helpful and very clear (and that was my very same approach), but comments are invaluable, please keep your code updated as suggested!

  9. Jørgen S. Nicolaysen:

    Hi
    After writing a heavy javascript webapp I would certainly not do this. It’s fine for pages not requiring much javascript.
    Here is some simple point that might be worth looking at:
    http://www.jblotus.com/2013/01/13/common-javascript-gotchas/

    It’s one thing I check in my applications, that is the variables lookated under the DOM tab in firebug. Ideally I should have introduced none there. I get really worried when I see sites with a lot of single variables floating around there that can easily get swappet out by some others code. (BTW; Even on this page there is a md5sum of 900150983cd24fb0d6963f7d28e17f72 floating around on this page anyway, its the md5sum of ‘abc’ …)

    I would recommend the book:
    “Object Oriented Javascript” by Stoyan Stefanov

    • 100% agree. For the most part, I just wanted to help beginner-ish JavaScript developers to see how helpful it is to have a nice, organized structure for your JavaScript.

      Most of the projects I’ve worked on lately are fairly small, single-purpose type sites and apps, so for those, this works fine for me.

      As for that variable you mention, I’m not sure exactly what that is. It’s not anything I recognize from my own scripts, so it might be something to do with the ads that display…? Not sure.

  10. Very interesting structure. It helps reading and understanding the code.

    I’d suggest never using this variable inside it. As you pointed out, it may lead to referencing the wrong object. And also makes it confusing to understand what it is, when somebody goes directly to some code wanting to quicky check something.

    I myself never use the this variable. I always create another variable with a meaningful name and assign this to it.

    Also, I’d suggest not using the s variable. Avoid 1-leter names. All objects and functions should be equally accessible inside and outside PrimaryNameSpace, so just use it. If you wanna make js file smaller, just use YUICompressor.

  11. A quick question, what plugin do you use for code highlighting and previewing comments?

    • Click the question mark in the top right of the code examples for a link to the syntax highlighter, it’s called “Google Syntax Highlighter”, and it’s one of the older versions.

      The comments preview is this one.

  12. I’d like an update/new post. What’s your “current” current JavaScript design pattern?

    • I don’t think it’s changed much. I don’t always use this, especially if it’s just something small for a small project.

      I just finished reading Nicholas Zakas’ Maintainable JavaScript, and although he’s mainly speaking to developers working on large teams, I love the stuff he recommends in there and I’m hoping to start incorporating some of it into my projects. I may end up writing a post discussing some of his suggestions. Definitely a must-read for anyone doing JS in a team environment.

  13. Barış Güler:

    This attitude can be an alternative maybe:


    var NAMESPACE= NAMESPACE || {};

    NAMESPACE.test = {
    config : {
    variable1 : 1,
    variable2 : 2
    },
    init : function(_namespace, _test, _config, _utils) {
    console.log('initialized...');
    NS = {};
    NS.TS = {};
    NS.TS.CFG = {};
    NS.TS.UTL = {};
    $.extend(NS, _namespace);
    $.extend(NS.TS, _test);
    $.extend(NS.TS.CFG, _config);
    $.extend(NS.TS.UTL, _utils);

    NS.TS.UTL.goHome();

    },
    utils : {
    goHome : function() {
    console.log('going home...');
    }
    }
    }

    $( document ).ready(function() {
    NAMESPACE.test.init(NAMESPACE, NAMESPACE.test, NAMESPACE.test.config, NAMESPACE.test.utils);
    });

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field. If you use keywords, your comment will be deleted, or your name will be replaced with the alias from your email address. No foul language, please. Thank you for cooperating.

Instructions for code snippets: Wrap inline code in <code> tags; wrap blocks of code in <pre> and <code> tags. When you want your HTML to display on the page in a code snippet inside of <code> tags, make sure you use &lt; and &gt; instead of < and >, otherwise your code will be eaten by pink unicorns.