Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Explain difference between revealing module pattern and using a constructor as namespace
//create our "FOO" namespace
window.FOO = window.FOO || {};
FOO.app1 = {
bar : 'foo',
init : function(){
//this wont work as expected since timeout changes scope
// the same would happen if it was an event handler like
// "onclick", "onload", etc..
setTimeout(this.logBar, 15);
},
logBar : function(){
console.log('app1: '+ this.bar);
}
};
FOO.app1.init();
// I've seen some people using this pattern in a couple places
// It has the same output as using a literal object (since "new function"
// returns a new object).
FOO.app2 = new function() {
this.bar = 'foo';
this.init = function() {
//this wont work as expected since timeout changes scope
// the same would happen if it was an event handler like
// "onclick", "onload", etc..
setTimeout(this.logBar, 15);
};
this.logBar = function(){
console.log('app2: '+ this.bar);
};
}
FOO.app2.init();
FOO.app3 = (function() {
//properties that should be exported, we only add stuff to this object if
//it needs to be public and we reference all functions internally as if it
//wasn't part of this object
var app = {
bar : 'foo'
};
function init() {
//work as expected
setTimeout(logBar, 15);
}
function logBar(){
console.log('app3: '+ app.bar);
}
// Export API
// ----------
// we only do it later so we avoid using the "this" keyword or "app.method()"
// through our module code, it helps to reduce scope issues and keeps code
// organized. It's also easier to spot what is public and what isn't.
//
// If we didn't needed to expose "bar" we would just return
// a plain object like:
// {
// init : init,
// logBar : logBar
// }
app.init = init;
app.logBar = logBar;
return app;
}());
FOO.app3.init();
@millermedeiros

This comment has been minimized.

Copy link
Owner Author

commented Sep 2, 2011

I just got an e-mail asking the difference about using the revealing module pattern, plain object and new function to create namespaces.

I guess the code explain better than what I could do with words why I usually pick the revealing module pattern and why I only expose the API at the end of the module definition.

It is also related to my other gist: https://gist.github.com/1188835

Only use constructors (new Foo()) when you need to instantiate multiple objects, if it is a static object, use the revealing module pattern or a plain object.

@ghost

This comment has been minimized.

Copy link

commented Sep 2, 2011

I'd like to understand but I need a bit more.
Is there 2 examples above, one w/ new and one w/ module pattern?
Also would this recommendation apply to node, as I see window there.

@millermedeiros

This comment has been minimized.

Copy link
Owner Author

commented Sep 2, 2011

on node.js you don't need to worry about global variables or name collision since each module is on a separate file, node.js already have the exports object... On node.js the code would be written as:

exports.bar = 'foo';

function init() {
    //work as expected
    setTimeout(logBar, 15);
}

function logBar(){
    console.log('app4: '+ exports.bar);
}

exports.init = init;
exports.logBar = logBar;

or you could also do like:

var app = {
    bar : 'foo'
};

function init() {
    //work as expected
    setTimeout(logBar, 15);
}

function logBar(){
    console.log('app3: '+ app.bar);
}

app.init = init;
app.logBar = logBar;

//expose API
module.exports = app;
@paullewis

This comment has been minimized.

Copy link

commented Sep 15, 2011

Really nice write-up, Miller! :) Turns out

FOO.thingy = new function() {
  // ... my epic wonder code
}

doesn't pass JSHint or JSLint so I've had to stop doing that :(

I'm rather fond of the exporting style, so I might give that a whirl!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.