"JohnS" <js*************@optusnet.com.au> wrote in message
news:3f***********************@news.optusnet.com.a u...
Single is a reference to a function. But calling Single(),
returns an object. In fact, Single() == new Single(), always.
As I wrote the Single class it was intended that all calls to it use
the - new - keyword.
I now understand why I was confused. When calling Single(),
the instance variable was inited with the global this. Arghh!
So, you are right, you need the new keyword to get a new this.
But, after the first call of new Single(), you can call
Single() to get the instance.
If you can guarantee that the first call uses - new - and that all calls
that do not use - new - happen after that initial call then you probably
do not want a class at all. Maybe one object assigned to a global
property will do the job sufficiently:-
var Single = {
prop1:1,
prop2:"anyString",
getProp1:function(){
return this.prop1;
},
setProp1:function(x){
this.prop1 = x;
},
getProp2:function(){
return prop2;
}
}
- so all code could just refer to the same object by the identifier
Single.
I think I'll change the constructor to create a new Single()
if this is global.
<snip>
You could do that but you would need a reliable test for the global
object and that would be extra work. If you just want to call a
function - Single() - (without the - new - keyword) and have it always
return the same (non-global) object then there are many aproaches, for
example:-
var Single = (function(){
var instance = null;
function InnerSingle(){
//actual constructor.
this.X = "something";
... //constructor function body
}
InnerSingle.prototype.getX = function(){
return this.X; //example method;
}
return (function(){
if(!instance){
instance = new InnerSingle();
}
return instance;
})
})();
called as - var obj = Single();
- here the real class is the InnerSingle class, whose constructor is
private (inaccessible outside the closure). The rest is just a wrapper
to make acquiring a reference to the one instance convenient. There are
probably at lest another half a dozen ways of achieving the same, using
object literal within the closure, for example:-
var Single = (function(){
var instance = null;
return (function(){
if(!instance){
instance = {
X:"something",
getX:function(){
return this.X;
}
};
}
return instance;
})
})();
-or-
var Single = (function(){
var instance = {
X:"something",
getX:function(){
return this.X;
}
};
return (funciton(){
return instance;
})
})();
called as - var obj = Single();
Alternatively you could return to your original public static -
getInstance - approach. In JavaScript you cannot have a "class" without
a public constructor, while a singleton probably should not have a
public constructor. However, a similar approach as used above could
emulate a class with a public static getInstance method but no
constructor. In this case the - Single - object is not a function (so it
cannot be called as a constructor), instead it is an object with one
public method:-
var Single = (function(){
var instance = null;
function InnerSingle(){
//actual constructor.
this.X = "something";
... //constructor function body
}
InnerSingle.prototype.getX = function(){
return this.X; //example method;
}
return ({
getInstance:function(){
if(!instance){
instance = new InnerSingle();
}
return instance;
}
});
})();
called as - var obj = Single.getInstance();
- the outward appearance and behaviour is that of a class without a
public constructor but with a public static - getInstace - method.
A similar structure could also be used to implement a class with no
public constructor and a factory method that returned a unique new
object on each invocation.
Richard.