1
\$\begingroup\$

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

\$\endgroup\$
2
  • \$\begingroup\$ Is that java factory? \$\endgroup\$ Jun 8, 2012 at 14:57
  • \$\begingroup\$ Is there a reason why you don't use an object literal? \$\endgroup\$
    – Ege Özcan
    Jun 8, 2012 at 16:16

1 Answer 1

2
\$\begingroup\$
  • 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'
    }
}());
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.