Created
September 2, 2011 17:29
-
-
Save millermedeiros/1189235 to your computer and use it in GitHub Desktop.
Explain difference between revealing module pattern and using a constructor as namespace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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(); |
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;
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
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.