0

I was just looking into ways of defining singletons in JavaScript, and after looking into a few samples I thought about the following way which I haven't found anywhere:

function MyClass() {
   if (MyClass._sharedInstance === undefined) {
      // actual constructor code

      MyClass._sharedInstance = this;
   }
   return MyClass._sharedInstance;
}

MyClass._sharedInstance = undefined;

Seems to work fine... but the fact that I couldn't find this anywhere makes me suspicious. Is there any reason not to do a singleton that way, especially considering the many little pitfalls of JavaScript. I know that by simply doing a var MyClass = { /* MyClass Stuff */ } I can achieve a singleton with less code, but for the sake of consistency I would like to define all my classes using prototypes.

BlackWolf
  • 5,239
  • 5
  • 33
  • 60
  • What advantage does this have over the "module" pattern? – user2864740 Jun 11 '14 at 23:23
  • 3
    What I don't understand is what problem this solves. How will it be used? – Travis J Jun 11 '14 at 23:23
  • 1
    "*for the sake of consistency I would like to define all my classes using prototypes*" - but for a singleton object you don't need a class, and no prototype to share anything! – Bergi Jun 11 '14 at 23:28
  • As I said, the only reason I'd do this is for consistency. @Bergi you are probably right, I am fairly new to OOP in JavaScript so a lot of my thinking is likely to still be influenced by "real" OOP languages. In my head, a singleton is just a special kind of class, so it makes sense to define it as such. Seems to be different in JS, though... – BlackWolf Jun 12 '14 at 08:22
  • I'd say that you are too much influenced by "class-only" languages, and you should start with some *real* OOP languages :-) – Bergi Jun 12 '14 at 12:22

1 Answers1

1

The proposed solution does not seem to "solve" anything1; as such, I recommend a standard variation of a "simple module pattern" using an idiomatic IIFE:

MySingleton = (function () {
    // This function is only executed once
    // and whatever is returned is the singleton.
    return {
       // Expose members here
    };
})();

Depending on specific need a new'ed object could also be returned, making this pattern flexible without the need to introduce a separate "singleton" field and guard, e.g.

MySingleton = (function () {
    // Contrived, but valid - any object returned
    // functions as the singleton.
    function MyClass {}
    return new MyClass();
})();

1If anything, it may lead to some "WTF?" moments when new MyClass() returns a shared/singleton object which is not "normal" behavior.

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • You are right that it does not solve anything besides allowing for a consistent way to define "classes" in JavaScript using prototyping. You are also probably right about the WTF-moment, but the same thing could be said about singletons in Java/C#/..., couldn't it? Anyway, I will go with the standard behaviour as you suggested and not use the prototyping solution. – BlackWolf Jun 12 '14 at 08:17
  • @user2864740: Notice that your second example (with the local `MyClass`, returning an instance from the IEFE) is equivalent to the `new (function MyClass(){…})` approach and has the same issues. – Bergi Jun 12 '14 at 12:23