Singletons with Functions

Previously, I had asked Which is Better, using var o = new function(){...} or var o = function(){..}();. At the time, it really just seemed to fall on personal preference. Both seemed to create singletons. It's just that some people like to do it one way while others perfer to do it the other way.

A commenter on my recent article at Digital Web, Objectifying JavaScript, however, pointed out that you could still instantiate new objects using the first code example. Here's how:

var o = new function() { ... }; 
var newO = new o.constructor();

What's interesting here is that I can create a new object using the constructor property which holds a reference to the original function. In fact, if I wanted to, I could instantiate a new object using the constructor property of my newO object which would still call the original anonymous function.

If you still wanted to use the original approach, you'd have to nullify the constructor. This would prevent people from using the property to construct new objects.

var o = new function(){ this.constructor = null; };

You learn something new every day.

Published September 20, 2006
Categorized as JavaScript
Short URL: https://snook.ca/s/676

Conversation

10 Comments · RSS feed
Bramus! said on September 21, 2006

Jonathan, once again a great tip! My javascript knowledge has been getting bigger and bigger with every post you make!

Anthony said on September 21, 2006

Succinct and powerful - thanks (to you and the commenter).

The Objectifying... article is proving very handy - The explanation of prototyping especially so.

Spotted your little clickable lightbulb yesterday too!

Alexei said on September 21, 2006

Jonathan,
Thanks for mentioning.
Concerning the method of setting null to the constructor : doesn't it seem like a kind of hack? It is a matter of preferences certainly and I know the discussion is probably over but let me introduce yet another variant. It's still a second approach but returns a constructor function, not an object itself:

var MyConstructor = (function()  {
      var instance = null;

      function myConstructor(name)  {
          if (instance) {
             return instance;
          }
          this.name = name;
          instance = this;
       }
       return myConstructor;
})();

Sorry if it's just a duplicate of already mentioned methods.

Dustin Diaz said on September 27, 2006

It almost seems as if then, why in the world would you create a singleton-like object and expect to instantiate it again to make another object.

In any case, the best place that I've found singletons used for is for procedural page set up type stuff; eg, the areas where you set up events, create new objects, and manage state between things of different sorts.

Singletons are good for consumers and subscribers.

Reusable classes are meant to be developed by producers and publishers.

Alexei said on September 28, 2006

"Why in the world..."?

It always puzzled me when people are so self-confident.
I provide a class. It is a black box. Consumer or developer doesn't necessarily have to know its interior implementation. It can be instantiated conditionally on different stages of system operation. I don't really know when. I just know that it can be instantiated only once. It is a singleton. It is not just a global static instance presented in literal object creation technique. Do you feel the difference?
Could you read the following from wiki “http://en.wikipedia.org/wiki/Singleton_pattern”:

"... Note the distinction between a simple static instance of a class and a singleton. Although a singleton can be implemented as a static instance, it can also be lazily constructed, requiring no memory or resources until needed."

Dustin Diaz said on October 05, 2006

Alexei,
I won't deny the self-confidence. Self-confidence is good. You should be more surprised in the fact that people don't always design correctly.

Note the distinctions between consumers and publishers. Consumers are the folks who use the class. Producers are the ones who make the class. It should not be a black box to the Producer.

mental said on October 05, 2006

There's growing consensus that singletons are an anti-pattern. So maybe the correct answer as to which to use is neither.

Alexei said on October 06, 2006

Dustin,

I believe that a "producer" who is using third party library is also a consumer. Black box concept is useful regardless of point of view.
According to your explanations there is some "ultimiate" producer - the only one hwo can "produce" singletons?
I think that singleton IS a class and it can be instantiated at any time without sacred knowledge of the "producer" that it IS a singleton.
I believe that the article I had cited clearly explains the distinction and my point of view. I cannot add anything.

Attila Szabo said on January 08, 2007

I wrote a short example for trying this out but somehow the object instantiated through .constructor is not the same as the original object.

var objSingletion2 = new function(){
        // private variables
        var _name = '';
        var _age = 0;

        // public variable
        this.publicVariable = 'I am a public variable';

        // methods
        function Constructor(){
            alert('Constructor is called!');
        }

        Constructor();
    };

    var obj2 = objSingletion2.constructor();
    alert(objSingletion2.publicVariable);
    alert(obj2.publicVariable);

Can someone explain me why I cannot access obj2.publicVariable, whereas it is accessible from the first object?

Attila Szabo said on January 09, 2007

Sorry for my previous post. I left out new operator.

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.