Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Javascript (http://www.velocityreviews.com/forums/f68-javascript.html)
-   -   Singleton in JavaScript (http://www.velocityreviews.com/forums/t871751-singleton-in-javascript.html)

JohnS 08-21-2003 07:20 AM

Singleton in JavaScript
 
Hi,

A lot of functions (classes) in my JavaScript app are singletons. So, I have
been exploring ways making JavaScript functions singletons. I thought I'ld
run one idea past you all and get some feed back.

The usual method of making singletons is to have a static member that
returns one instance of the class. But, JavaScript has no notion of static.
The closest it has is prototype functions.

// The singleton class
function Single() {
// call the "static" GetInstance()
return Single.prototype.GetInstance();
}

// The only instance.
Single.prototype._single = null;

// static function
Single.prototype.GetInstance = function() {
if( !Single.prototype._single ) {
Single.prototype._single = this;
}
return Single.prototype._single;
}
----------

So, "new Single() == new Single()" is true.
Or "new Single() == Single.prototype.GetInstance()"

What do you all think? Is the "new Single()" going to be confusing? Is there
are way to do "Single.GetInstance()"? I think the prototype version is
unweildy.

-------------------------------------------------------------

When can I refer to prototype functions or prototypes full stop? It appears
that "this.GetInstance" exists in "new Single()", but I can't call it.

JohnS



Richard Cornford 08-21-2003 08:01 AM

Re: Singleton in JavaScript
 
"JohnS" <jsietsma_public@optusnet.com.au> wrote in message
news:3f4472bb$0$28123$afc38c87@news.optusnet.com.a u...
<snip>
>... . But, JavaScript has no notion of static.
> The closest it has is prototype functions.

<snip>

In JavaScript public static members are created a properties of the
function object that represents the constructor:-

function Single() {
if(!Single.instance){
//construct objectc
Single.instance = this;
}
return Single.instance;
}

Single.instance = null; //public static member

- and private static members may be emulated by forming a closure with
the constructor:-

var Single = (function(){
var instance = null; //private static member
return (function(){ //return the constructor function
if(!instance){
//construct object
instance = this;
}
return instance;
});
})(); //inline execution of anonymous function

- (or the prototype, but it is cleaner and more flexible with the
constructor).

>... Is there
> are way to do "Single.GetInstance()"?

<snip>

Yes, public static methods are completely normal:-

Single.GetInstance = function(){
. . . //function body
}

Richard.



JohnS 08-25-2003 04:15 AM

Re: Singleton in JavaScript
 

That's great. So, I can drop the prototype and just put GetInstance straight
into the function. I didn't know that.

The second example threw me for a bit. It seemed like it should return a
typeof "function" . But, it returns a typeof "object". So, it's contructing
an object without using the "new" keyword. Strange.

It seems to mean, that when you call a straight function, the function
becomes an object and then executes. If you return "this", you have a
function instance/object.

Also, if you have an inner function, "this" refers to the outer "this".

Thanks for your help.

JohnS

----- Original Message -----
From: "Richard Cornford" <Richard@litotes.demon.co.uk>
Newsgroups: comp.lang.javascript
Sent: Thursday, August 21, 2003 6:01 PM
Subject: Re: Singleton in JavaScript


> "JohnS" <jsietsma_public@optusnet.com.au> wrote in message
> news:3f4472bb$0$28123$afc38c87@news.optusnet.com.a u...
> <snip>
> >... . But, JavaScript has no notion of static.
> > The closest it has is prototype functions.

> <snip>
>
> In JavaScript public static members are created a properties of the
> function object that represents the constructor:-
>
> function Single() {
> if(!Single.instance){
> //construct objectc
> Single.instance = this;
> }
> return Single.instance;
> }
>
> Single.instance = null; //public static member
>
> - and private static members may be emulated by forming a closure with
> the constructor:-
>
> var Single = (function(){
> var instance = null; //private static member
> return (function(){ //return the constructor function
> if(!instance){
> //construct object
> instance = this;
> }
> return instance;
> });
> })(); //inline execution of anonymous function
>
> - (or the prototype, but it is cleaner and more flexible with the
> constructor).
>
> >... Is there
> > are way to do "Single.GetInstance()"?

> <snip>
>
> Yes, public static methods are completely normal:-
>
> Single.GetInstance = function(){
> . . . //function body
> }
>
> Richard.
>
>




asdf asdf 08-26-2003 03:12 AM

Re: Singleton in JavaScript
 
Hi, I just wanted to add a tiny thing that I'm not sure was mentioned.
Another way of declaring a static function is:

function Single.GetInstance() {
....
}

This way your call stack will have a named function instead of an
anonymous one.



"Richard Cornford" <Richard@litotes.demon.co.uk> wrote in message news:<bi1u91$be2$1$8300dec7@news.demon.co.uk>...
>
> Single.GetInstance = function(){
> . . . //function body
> }
>
> Richard.


Lasse Reichstein Nielsen 08-26-2003 10:27 AM

Re: Singleton in JavaScript
 
b0b0b0b@yahoo.com (asdf asdf) writes:

> Hi, I just wanted to add a tiny thing that I'm not sure was mentioned.
> Another way of declaring a static function is:
>
> function Single.GetInstance() {
> ...
> }


Not in ECMAScript v3 or any Javascript I have seen. It doesn't appear
to work in JScript.NET (which implements the proposed ECMAScript v4).

It is just a syntax error. It would be very nice is that syntax was
supported, but it isn't.

> This way your call stack will have a named function instead of an
> anonymous one.


You could write either

function getInstance() {...}
Single.GetInstance = getInstance;

or

Single.GetInstacne = function GetInstance() {...}

Just remember that there is no difference between a "named" function
and an anonymous one. It is just a function object, which is an anonymous
value, that has been assigned to a variable.

/L 'please don't top post'.
--
Lasse Reichstein Nielsen - lrn@hotpop.com
Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit.html>
'Faith without judgement merely degrades the spirit divine.'

Richard Cornford 08-26-2003 10:34 PM

Re: Singleton in JavaScript
 
"JohnS" <jsietsma_public@optusnet.com.au> wrote in message
news:3f498d74$0$15131$afc38c87@news.optusnet.com.a u...
<snip>
>The second example threw me for a bit. It seemed like it should
>return a typeof "function" . But, it returns a typeof "object".
>So, it's contructing an object without using the "new" keyword.
>Strange.


When you say 'it returns a typeof "object"', what do you men by "it".
Single should be a reference to a function (the constructor returned by
the incline function expression call), as a constructor, calling - new
Single(); - will return an object. A new object the first time it is
called and that same object on every subsequent call. However, if you
call any custom JavaScript constructor without using the - new - keyword
you will not get a new object constructed and there is every chance that
the function will execute as global code and the - this - keyword will
refer to the global object.

>It seems to mean, that when you call a straight function, the
>function becomes an object and then executes. If you return
>"this", you have a function instance/object.


If you call a global function the - this - keyword will refer to the
global object, if - this - is returned then the object returned will be
the global object.

>Also, if you have an inner function, "this" refers to the
>outer "this".


No it will not. For inner functions - this - could be one of may
objects. If the inner function is assigned as a method of an object
(including function objects) then - this - refers to that object, else
an inner function - this - will be the global object unless that inner
function is called as a constructor using the - new - keyword, in which
case - this - refers to the new object. The specifics are described in
the ECMA Script specification.

Richard.



JohnS 08-27-2003 12:03 AM

Re: Singleton in JavaScript
 
Single is a reference to a function. But calling Single(), returns an
object. In fact, Single() == new Single(), always.

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.

I think I'll change the constructor to create a new Single() if this is
global.

Thanks for your explainations.

----------------------------------------------------------------------------
-------
Here the the test code I used:
note: If you call Single() before new Single(), isObjectGlobal() returns
true.


function p( msg ) {
document.write( msg + "<BR>" );
}

var gThis = this;
function isObjectGlobalThis( myThis ) {
return myThis == gThis;
}

// Singleton
var Single = (function(){
var instance = null; //private static member
return (function(){ //return the constructor function
if(!instance){
//construct object
p( "Constructing this" );
instance = this;
}
p( "Returning this" );
return instance;
});
})(); //inline execution of anonymous function


function test() {

p( "Calling new Single()" );
single1 = new Single();
p( "" );

p( "Calling Single()" );
single2 = Single();
p( "" );


p( "typeof Single: " + typeof Single );
p( "typeof Single(): " + typeof single1 );
p( "typeof new Single(): " + typeof single2 );
p( "" );

p( "Single() == new Single(): " + (single1 == single2) );
p( "" );

p( "isObjectGlobalThis( test ): " + isObjectGlobalThis( this ) );

p( "isObjectGlobalThis( Single() ): " + isObjectGlobalThis( single1 ) );
p( "isObjectGlobalThis( new Single() ): " + isObjectGlobalThis(
single2 ) );
}

--------------------------------------------------------------------------
Output is:
Calling new Single()
Constructing this
Returning this

Calling Single()
Returning this

typeof Single: function
typeof Single(): object
typeof new Single(): object

Single() == new Single(): true

isObjectGlobalThis( test ): true
isObjectGlobalThis( Single() ): false
isObjectGlobalThis( new Single() ): false


"Richard Cornford" <Richard@litotes.demon.co.uk> wrote in message
news:bign9k$n44$1$8300dec7@news.demon.co.uk...
> "JohnS" <jsietsma_public@optusnet.com.au> wrote in message
> news:3f498d74$0$15131$afc38c87@news.optusnet.com.a u...
> <snip>
> >The second example threw me for a bit. It seemed like it should
> >return a typeof "function" . But, it returns a typeof "object".
> >So, it's contructing an object without using the "new" keyword.
> >Strange.

>
> When you say 'it returns a typeof "object"', what do you men by "it".
> Single should be a reference to a function (the constructor returned by
> the incline function expression call), as a constructor, calling - new
> Single(); - will return an object. A new object the first time it is
> called and that same object on every subsequent call. However, if you
> call any custom JavaScript constructor without using the - new - keyword
> you will not get a new object constructed and there is every chance that
> the function will execute as global code and the - this - keyword will
> refer to the global object.
>
> >It seems to mean, that when you call a straight function, the
> >function becomes an object and then executes. If you return
> >"this", you have a function instance/object.

>
> If you call a global function the - this - keyword will refer to the
> global object, if - this - is returned then the object returned will be
> the global object.
>
> >Also, if you have an inner function, "this" refers to the
> >outer "this".

>
> No it will not. For inner functions - this - could be one of may
> objects. If the inner function is assigned as a method of an object
> (including function objects) then - this - refers to that object, else
> an inner function - this - will be the global object unless that inner
> function is called as a constructor using the - new - keyword, in which
> case - this - refers to the new object. The specifics are described in
> the ECMA Script specification.
>
> Richard.
>
>




Richard Cornford 08-27-2003 02:18 AM

Re: Singleton in JavaScript
 
"JohnS" <jsietsma_public@optusnet.com.au> wrote in message
news:3f4bf54f$0$15136$afc38c87@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.



asdf asdf 08-27-2003 05:06 AM

Re: Singleton in JavaScript
 
Hi -- I believe it works in IE6, which is all I code against. Thanks,
Ron

b0b0b0b@yahoo.com (asdf asdf) wrote in message news:<6f24588b.0308251912.763588d7@posting.google. com>...
> Hi, I just wanted to add a tiny thing that I'm not sure was mentioned.
> Another way of declaring a static function is:
>
> function Single.GetInstance() {
> ...
> }
>
> This way your call stack will have a named function instead of an
> anonymous one.


Lasse Reichstein Nielsen 08-27-2003 07:59 AM

Re: Singleton in JavaScript
 
b0b0b0b@yahoo.com (asdf asdf) writes:

> Hi -- I believe it works in IE6, which is all I code against.


You are actually right.

function x(){}
function x.y (){alert('foo');}
x.y(); // alerts "foo"

It is important that x is a function. It doesn't work if it is just a
normal object (which was what I first tried).

/L
--
Lasse Reichstein Nielsen - lrn@hotpop.com
Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit.html>
'Faith without judgement merely degrades the spirit divine.'


All times are GMT. The time now is 06:34 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.