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 commonly 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.
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.
I’ve been there :-) I’ve moved away from this pattern towards the pubsub based modular pattern. e.g.:
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.
Thanks, this looks interesting. I would certainly consider moving to something better. I’ll have to look into this.
Here’s a great library for pub/sub if you are interested: https://gist.github.com/661855
I prefer function rather the object as main “namespace”. My aproach is quite similar thought:
If you write:
function SomeFunction(...){
_private = function(){
}
}
_private is a global variable, so, it’s accessible from the outside.
You need to put
var
before or declare function like this:function SomeFunction(...){
function _private(){
}
}
I also like
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:
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.
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:
(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 passjQuery
, and then assign it to$
in your scope. Secondly, you don't want to overwrite your namespace - that's why we usewindow.MyObject = window.MyObject || {}
, which will returnMyObject
if it already exists, so we can expand it - see the huge advantage here? Finally we haveundefined
. You may wonder why the heck do we need to put it there? Well, in older versions of ECMAScript you were able to redefineundefined
. 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.
Can someone explain why we need the outermost parentheses when defining the anon self-executing function?
Hopefully this will get noticed, since it’s an old thread. Thank you!
I think you’ll get a good explanation here:
http://benalman.com/news/2010/11/immediately-invoked-function-expression/
This quote might help:
That’s very useful. Thank you.
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.
Yes, there’s a note about that in the “update” box at the end of the article above.
couple of things to help you, I tend to use this:
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:
One last thing you can look at is jQuery’s $.proxy. This allows you to keep scope of “this” when calling functions:
Just my two cents.
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!
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.
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 assignthis
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 outsidePrimaryNameSpace
, so just use it. If you wanna make js file smaller, just use YUICompressor.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.
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.
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);
});
I know this is a rather old article, but just wanted to point out (as a few commenters have alluded to) that the existing concept of a module pattern (that you reference @ the start of your article) is a bit different than the code you’re using.
The defining feature of the module pattern is that it uses closure to create privacy, which is normally not available in javascript. It uses an immediately invoked function expression (similar to the jQuery pattern you’re using at the bottom of your script) to creare a closure around your object data (ie settings, init, etc.) and return a public API which has access to the entire contents of the object, but only exposes a subset of that content to the rest of the application.
Yes, absolutely. In fact, my knowledge of the module pattern is pretty limited.
As I mention at the start, my example is a “variation” of the module pattern and has basically served my purposes, which is not in very large applications, usually just one-page side projects and whatnot.
Very nice article, clean and easy to understand, well I learned more from the comments below lol…
Thanks all