I needed a singleton in JavaScript in order to make a DataManager which is called multiple times, but I just want it to load its data only the first time it is called, then give pieces of the data out view public methods, never loading the initial data again.
I found a number of approaches to building singletons in JavaScript but this one seems to have everything I need.
Does anyone see any kind of problem this singleton is going to have for the uses I need it for?
<!DOCTYPE html>
<html>
<head>
<title>test singleton</title>
<script type="text/javascript">
var DatapodManager = (function() {
var instantiated;
that = this;
//DEFINE INTERNAL VARIABLES HERE:
var message = '';
function init() {
//LOAD DATA ONCE HERE:
that.message = 'singleton message defined at: ' + getMilliseconds();
//ALLOW PUBLIC ACCESS TO SINGLETON DATA HERE:
return {
getMessage : function() {
return that.message;
},
id : '1234'
}
}
return {
getInstance : function() {
if(!instantiated) {
instantiated = init();
}
return instantiated;
}
}
})()
function dowait() {
for( x = 1; x <= 10000000; x++) {
var y = 1000;
var z = 2000;
var b = y * z;
}
}
function getMilliseconds() {
var d = new Date();
return d.getMilliseconds();
}
window.onload = function() {
console.log('getting first singleton message at: '+getMilliseconds());
console.log(DatapodManager.getInstance().getMessage());
dowait();
console.log('getting second singleton message at: '+getMilliseconds());
console.log(DatapodManager.getInstance().getMessage());
console.log('the static id is '+DatapodManager.getInstance().id);
};
</script>
</head>
<body></body>
Output:
enter image description here
-
\$\begingroup\$ Is that java factory? \$\endgroup\$Florian Margaine– Florian Margaine2012年06月08日 14:57:33 +00:00Commented Jun 8, 2012 at 14:57
-
\$\begingroup\$ Is there a reason why you don't use an object literal? \$\endgroup\$Ege Özcan– Ege Özcan2012年06月08日 16:16:51 +00:00Commented Jun 8, 2012 at 16:16
1 Answer 1
Once you start to chain properties or function calls, you incur performance penalty due to scope differences. It's best you keep the property/function depth to a minimum. This ain't Java or AS3 that needs deep namespacing.
What's the idea of
getInstance()
? Can't the singleton module itself be the instance?Regarding the output image, it is correct. You get the first message at 440ms, then the singleton created the message at 442ms during
init()
. The next call you made is at 482ms. Since the instance was already created, the same message (the one created at 442ms) was used.
Here's a very short version of it. Basically, I just removed getInstance()
and made DatapodManager
the instance. No visible speed difference but you have shorter code. I also preserved the idea of it being a closure in case you ever needed private properties:
var DatapodManager = (function () {
return {
message: 'singleton message defined at: ' + getMilliseconds(),
getMessage: function () {
return this.message
},
id: '1234'
}
}());