Singleton without a closure

Warning: anti-pattern ahead.

Mwahaha, I feel like a ninja. I mean a ninja by Doug Crockford's definition which means someone who finds a mistake in the language's design, decides it's cool and abuses it.

So there you go. Regular expression objects are created only once if you're using a literal. Such an object can be used to store the single instance of a Singleton() constructor.

Implementation

function Single() {
    "strict me not!";

    var re = / /;
    if (re.instance) {
        return re.instance;
    }
    re.instance = this;
    this.name = "Foo";

}

Single.prototype.getName = function () {
    return this.name;
};

Test

var s1 = new Single(),
    s2 = new Single();

console.log(s1 === s2); // true
console.log(s1.getName()); // "Foo"
s1.name = "dude";
console.log(s2.getName()); // "dude"

Pros

  • The prototype chain works fine
  • No closures
  • No public properties or globals to store the single instance

Cons

  • It's a hack
  • ES5 defines that reg exp literals should no longer work like this

Verdict

Don't use. Please :)

Tags:

4 Responses to “Singleton without a closure”

  1. Balázs Galambosi Says:

    Lol. Why not:


    function Single() {
    "strict me not!";

    if (Single.instance) {
    return Single.instance;
    }
    Single.instance = this;
    this.name = "Foo";
    }

  2. jdalton Says:

    At least IE, Safari, and Opera all fail this pattern because they evaluate the literal each time. Balázs’ suggestion is better.


    var Single = (function() {
    function Klass() { };
    function Single(name) {
    one.name = name || 'Foo';
    return one;
    }
    var one = new Klass;
    Single.prototype = Klass.prototype;
    return Single;
    })();

    Single.prototype.getName = function () {
    return this.name;
    };

    The it works cross-browser, the instance isn’t stored as an external property, and it allows `Single` to work when called as function or a constructor.

  3. jdalton Says:

    For a flavor more in line with the pattern you are trying to achieve:


    var Single = function(name) {
    function Klass() { };
    function Single(name) {
    name && (one.name = name);
    return one;
    }
    Single.prototype = Klass.prototype = window.Single.prototype;
    window.Single = Single;
    var one = new Klass;
    return Single(name);
    };

    Single.prototype.name = 'Foo';

    Single.prototype.getName = function () {
    return this.name;
    };

  4. Takaful Keluarga Says:

    Its like you read my mind! You seem to know a lot about this, such as you wrote the e book in it or something. I believe that you just can do with some percent to force the message home a bit, however instead of that, that is great blog. A fantastic read. I’ll definitely be back.

Leave a Reply