JavaScript namespacing – an alternative to JavaScript inheritance

When talking about JavaScript and inheritance, something that often go amiss from the discussion is the alternative of using proper namespacing instead.

Namespacing?

First, let’s establish that global variables are evil. Got that? Good. An alternative to that is to use an object to be the container for all functionality in a web site, e.g. the customer or product name. Let’s start with a simple example:

var Griffins = {};

I know, amazing, right? πŸ™‚

The idea here is that the empty Griffins object you have created will the super object to which everything else will belong. You can now add objects as part of that object, like this:

Griffins.Stewie = {
    evil : true,
    triesToKill : "Mom"
};

and

Griffins.Peter = {
    familyHead : true,
    responsible : false
};

Extending – not necessarily inheriting

As you can see from above, this technique allows you to to use just one global container, and then extend it with different objects and branches depending on desired functionality. The upside of it is that most objects become something like siblings to each other, rather than parent and child objects.

Compared to JavaScript inheritance

The reason I wanted to state that this might pose an alternative to JavaScript inheritance is that, in my experience, inheritance tends to be overused, and developers spend more time overriding functionality inherited from some sort of super object, instead of just focusing on the new object’s features. Basically, inheritance isn’t always the best way to go, whereas namespacing could be the best solution at hand instead.

Namespace assertion

Something to mention here is that if you have your code spread across multiple files, which seems very likely, to make sure the global object exists, you just need to add a little assertion to the top of each file using it, before you try to extend it:

if (typeof Griffins === "undefined") {
    Griffins = {};
}

Griffins.Lois = {
    strangelyHot : true,
    hasWeirdHusband : true
};

This code checks if Griffins is already defined, and if not, it creates a new namespace to add the Lois object to.

Reusage of methods across objects

Now you’re thinking that this approach results in a lot of redundant code, and being completely against DRY principles; on the contrary! The benefit is that from one object’s method, you can choose to just call the method of another, but within the right context. Let’s take a look at these two objects:

Griffins.Chris = {
    brainCapacity : "Low",
    getCapacity : function () {
        return this.brainCapacity;
    }
};

Griffins.Meg = {
    brainCapacity : "Decent",
    lowSelfEsteem : "Low self esteem"
    getCapacity : function () {
        var capacity = Griffins.Chris.getCapacity.apply(this, arguments);
        capacity += " - " + this.lowSelfEsteem;
        return capacity;
    }
};

// Returns "Low"
Griffins.Chris.getCapacity();

// Returns "Decent - Low self esteem"
Griffins.Meg.getCapacity();

What happens here is that the Griffins.Meg object reuses the getCapacity from the Griffins.Chris object, but calls it as itself, through the help of the apply method. I.e. the keyword this in the getCapacity for the Griffins.Chris object will then point to the Griffins.Meg object, getting the property brainCapacity from the correct object.

Evaluating options

So, what I wanted to say with this post is that JavaScript inheritance doesn’t have to be a bad thing, but that sometimes it’s just not the best way to approach a problem. Instead, good namespacing has proven to be very successful and a worthy alternative. Personally, I also think it’s very good for code clarity, instead of chasing up some prototype chains.

22 Comments

  • I think this is a great approach and it’s a good thing many people write about it. In fact, you inspired me to write about it πŸ™‚

  • Stefan Van Reeth says:

    After reading both Roberts and Harmens posts, one remark (agreeing on everything is sooo dull πŸ™‚ ): Robert approaches inheritance and namespacing as alternatives to each other, while I see the namespacing as an additional technique alongside inheritance. I feel Harmen also leans more towards that thought. At least he uses his namespaces pretty much the way I do, namely as the container for all code belonging to that particular project.

    I understand that Roberts example above is just that, an example. However, it would be way more logical to put the getCapacity function into a Person object and have Chris and Meg inherit from that. That structuring still allows both to do something extra with the result and makes both independent from each other. True, they now depend both on Person, but logically that makes more sense. Basic OOP stuff in fact.

    One example why the original example ain't such a good practice: say you need the Meg object in another project. In Roberts example you'll need to study the code to discover why the Chris object needs to be ported too, while in an inheritance approach it would be far easier to spot that a Person object should come over too. What's the difference then? In both scenarios we need to port two objects just to use Meg (hmm, sounds weird…). True, but what if we port say 50 person-like objects? Are we gonna study them all to discover what specific persons they depend on, or do we just import a generic Person and be gone with it? I know what I prefer…

    All this to say that in no way namespacing and inheritance should exclude each other. On the contrary, using both techniques leads to more logical, easier to maintain and more portable code. Why throw away decades of good practices? Last time I checked, OOP isn't restricted to classical languages. Serious JavaScript projects benefit also from the hard-learned OOP best practices.

    The true beaty of JavaScript 'namespacing' is that all newly introduced code is found under one global, avoiding the 'evil globals' problem gracefully. The second advantage is when a project demands externally produced modules. If everyone would namespace their code, function name clashes and the like would be a thing of the past.

    And those two reasons are enough to ALWAYS namespace things.

  • Robert Nyman says:

    Harmen,

    Thanks!

    Stefan,

    To begin with, no matter how you choose to work with inheritance, I'd say that namespacing is always a good idea and a great complement to other code!

    What I was also arguing for here is that OOP pricinples aren't always the best solution, especially for certain web scenarios. When it comes to extensive reusage of code, inheritance can naturally be a good thing, but from what I often see, it is way overused and complicaced in cases where it doesn't have to be.

    So, at times namespacing and inheritance complement each other just fine, but in ohter cases I really do think that namespacing alone can be sufficient.

  • Stefan Van Reeth says:

    Well Robert, I really DO try to think along with your vision, but I feel we are far away from each other when it comes to programming tactics. Indeed I am a strong believer in classic OOP principles, just because they feel so natural to me. Because I do use several languages at a time I tend to stay away from techniques that are too language specific? Maybe, never gave it a thought really.

    So, at times namespacing and inheritance complement each other just fine, but in other cases I really do think that namespacing alone can be sufficient.

    Putting it that way I'm almost tempted to agree with it. On the other hand I can't say I fully disagree either. In my experience I only find a use for pure namespacing when prototyping something new. After refactoring I always end up with inheritance chains. Considering we use largely different approaches, ending up with other solutions is no surprise.

    Mind you, Robert, I do find your views very refreshing. Shooting holes in them is just a way to come to a better understanding. Untill the next shootout πŸ˜‰

  • Robert Nyman says:

    Stefan,

    I do appreciate your feedback; hell, it's one of the reasons I allow comments, I don't want this web site to be just a one-way communication.

    I want to understand different views and takes, and how people value different criteria. I don't have to agree with all input, but just respect that there's usually more than one way to do something.

    Also, in the end I think it comes down a lot to personal experience: which kind of projects have one worked, with what kind of developers does one deliver code etc. So, it's all relative. πŸ™‚

  • Andy W says:

    In general, I'd agree that object composition should be used in place of inheritance in many places. However I'm a little uncomfortable with your Chris/Meg example.

    With this implementation, now we can't change the behaviour of Chris' getCapacity method without breaking the functionality for Meg (suppose Chris developed low self esteem too?). One option might be to create a generic getCapacity method (perhaps on Griffins) which could be used (and augmented as needed) by each family member.

  • Robert Nyman says:

    Andy W,

    Oh, absolutely, if you need to build on it, you would probably have some more generic object. It's just to exemplify reusage possibilities.

  • Stefan Van Reeth says:

    Reading back (been away a while), I can't do anything but agree whith Roberts last answer to me. Different people – different backgrounds – different tastes. So we can go on and on and on. Just lovely πŸ™‚

  • Robert Nyman says:

    Stefan,

    Thank you! πŸ™‚

  • […] post was inspired by a post that Robert Nyman wrote a while back. At the same time I was thinking about how to achieve private […]

  • […] JavaScript namespacing – an alternative to JavaScript inheritance […]

  • jQuery Howto says:

    Great article. Here is an article on how to use it with the jQuery object. In other words namespasing with the jQuery http://jquery-howto.blogspot.com/2009/01/namespace-your-javascript-function-and.html

  • Robert Nyman says:

    jQuery Howto,

    Thanks for the link!

  • […] 1 shows a popular way to namespace Javascript. In this case,if (  if the variable rp is not yet defined, it is declared as a new empty […]

  • Anirudh Vyas says:

    Hey,

    So say I have, XNamespace.js which is like:

    <code>

    ( function ( ) {

    X = {

    // stuff

    };

    X.LOG.info = function ( ) {

    };

    }) ( );

    </code>

    And then in another JS file, say YNamespace.js, I have got something like:

    <code>

    ( function ( ) {

    X.Y = {

    // stuff

    };

    X.Y.somethingFunky = function ( ) {

    };

    }) ( );

    </code>

    How do I ensure that X is available for Y? So far, the solution that I have come up with is:

    <code>

    if(typeof X === 'undefined') {

    document.write('');

    }

    </code>

    Which i Think is funky, Any better solutions ? I am pretty new to this kinda stuff, so I cant think of any better ones out there … Basically I wanna do something like dojo.require('X.Y.Z') and get the namespace.

    Suggestions?

    Regards

    Vyas, Anirudh

  • Robert Nyman says:

    Anirudh Vyas,

    Well, you could check for the existence, and if not's there, just create an empty container with curly braces (i.e. {}).

    In your code example, though, you create closures that doesn't return anything. If you want to extend objects from other functions/files, you need to make them globally available.

  • Juan Mendes says:

    I can't really agree with you on this one, though I appreciate the take. In this case, you are relying on all the instances to have a property defined brainCapacity, seems too coupled to me.

    The other problem I see is the fact the shared method is put into a random objext (the first on the list). Inheritance would create a logical place to put shared code. Here, you just have to know which of the objects has the shared method.

  • Robert Nyman says:

    Juan,

    I'd say it definitely depends on the situation. There are some cases when extending and just taking use of certain parts is more efficient and better for performance as well, while there are others where inheritance is the better way to go.

  • Angus Croll says:

    Nice article

    Didn't James Gosling once say that if he had to do Java all over again he's leave out inheritance? I think his point was that developers over-rely on inheritance to stay DRY and this makes for monstrous and meaningless hierarchies.

    In JavaScript we have call and apply so you don't need to pretend you need inheritance in order to get re-use.

  • Robert Nyman says:

    Angus,

    Thanks!

    And interesting about James Gosling, I never knew that!

  • Joe Francis says:

    This is some useful code for JavaScript Polymorphism

    /** This is our Person class */

    Person = function (id, name, age) {
    this.id = id;
    this.name = name;
    this.age = age;
    // alert(‘A new person has been accepted’);
    }

    /* definition of our Person class */
    Person.prototype = {
    /** wake person up */
    wake_up: function () {
    alert(‘A person is awake’);
    },

    /** retrieve person’s age */
    get_age: function () {
    return this.age;
    }
    }

    Inheritance_Manager = {};

    Inheritance_Manager.extend = function (subClass, baseClass) {
    function inheritance() { }
    inheritance.prototype = baseClass.prototype;
    subClass.prototype = new inheritance();
    subClass.prototype.constructor = subClass;
    subClass.baseConstructor = baseClass;
    subClass.superClass = baseClass.prototype;
    }

    Manager = function (id, name, age, salary) {
    Manager.baseConstructor.call(this, id, name, age);
    this.salary = salary;
    // alert(‘A manager has been registered.’);
    }

    Inheritance_Manager.extend(Manager, Person);

    Manager.prototype = {
    wake_up: function () {
    alert(‘I am in control’);
    }
    }

    var arrPeople = new Array();
    arrPeople[0] = new Person(1, ‘Joe Tester’, 26);
    arrPeople[1] = new Manager(1, ‘Joe Tester’, 26, ‘20.000’);

    for (var i in arrPeople) {
    arrPeople[i].wake_up();
    alert(arrPeople[i].get_age());
    }

    View full article with comments: here

  • Robert Nyman says:

    Joe,

    Cool, thanks for the tip!

Leave a Reply to Robert Nyman Cancel reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.