Singleton vs Singleton

  • Thread starter Michael Haufe (\TNO\)
  • Start date
M

Michael Haufe (\TNO\)

From looking at the code below:
--------------------------------------------------
var Singleton1 = (function(){
//...
return {
foo : function(){
//...
},
bar : function(){
//...
}
};
})();

var Singleton2 = new function(){
//...
this.foo = function(){
//...
};
this.bar = function(){
//...
};
};
-----------------------------------------------

Is there a good reason why jslint should complain about Singleton2,
but not Singleton1?

jslint message:
-----------------------------------------------
Problem at line 13 character 18: Weird construction. Delete 'new'.

var Singleton2 = new function(){

Problem at line 21 character 2: Missing '()' invoking a constructor.

};
-----------------------------------------------
 
R

Richard Cornford

From looking at the code below:
--------------------------------------------------
var Singleton1 = (function(){
//...
return {
foo : function(){
//...
},
bar : function(){
//...
}
};

})();

var Singleton2 = new function(){
//...
this.foo = function(){
//...
};
this.bar = function(){
//...
};};
<snip>

I wouldn't be surprised if the motivation followed from years of
seeing the - new - operator used for no reason other than to execute
the function. Examples were the new object created by implication was
never employed in the function body and so its creation (and setting
up ([[Prototype]] assignment, etc)) represented pure overhead. Where
just calling the function would achieve the same outcome without the
overheads, without the confusion of implying an object construction
process to the reader, and without the use of any more source code
characters.

Richard.
 
A

Asen Bozhilov

Michael said:
From looking at the code below:
--------------------------------------------------
var Singleton1 = (function(){
[...]
})();

var Singleton2 = new function(){
[...]
};

Both solutions allocate memory for instance properties, before i need
from your `Singleton` object.
I want Singleton with properties:
- Doesn't have constructor
- Create instance properties when i call `Singleton.getInstance()`
- Create instance properties only once

var x = Singleton.getInstance();
window.alert(typeof x.method1); //function
window.alert(typeof x.method2); //function
window.alert(Singleton.getInstance().method1 === x.method1); //true

How can i implement?
 
S

Scott Sauyet

I want Singleton with properties:
- Doesn't have constructor
- Create instance properties when i call `Singleton.getInstance()`
- Create instance properties only once

var x = Singleton.getInstance();
window.alert(typeof x.method1); //function
window.alert(typeof x.method2); //function
window.alert(Singleton.getInstance().method1 === x.method1); //true

This looks more complicated than necessary, but I think would work:

Singleton = (function() {
var instance = null;
return {
getInstance: function() {
if (instance == null) {
instance = {
method1: function() {},
method2: function() {},
}
}
return instance;
}
}
})();

Are there simplifications to be done here?

-- Scott
 
A

Asen Bozhilov

Scott said:
This looks more complicated than necessary, but I think would work:

But if i want my `Singleton` inherit from something, I'll be need to
modified my `getInstance' method. I don't want to do it this. In
`getInstance' i want to create only instance properties. I'll be
implement in:

var Singleton = {};
Singleton.getInstance = function()
{
this.method1 = function(){};
this.method2 = function(){};

this.getInstance = function(){
return this;
};
return this;
};
 
T

Thomas 'PointedEars' Lahn

Scott said:
This looks more complicated than necessary, but I think would work:

Singleton = (function() {
var instance = null;
return {
getInstance: function() {
if (instance == null) {
instance = {
method1: function() {},
method2: function() {},
}
}
return instance;
}
}
})();

Are there simplifications to be done here?

Only optimizations: Lose the trailing comma (increases compatibility), and
end statements and assignments with semicolon to distinguish them from
/Block/ statements (Pretty Printing).

And I cannot stress this too much: DO NOT do the whole nonsense in these
languages. You only need the singleton pattern where objects have no
initializer syntax, like in Java. Implementations of ECMAScript Ed 3.
forward instead allow

var instance = {
method1: function() {},
method2: function() {}
};


PointedEars
 
G

Garrett Smith

Why not?
This looks more complicated than necessary, but I think would work:
[snip]
It doesn't look complicated at all.
Are there simplifications to be done here?

I added var, removed the extra comma, and added a couple of semicolons
that were omitted.

I also removed the null assignment and null check.

var Singleton = (function() {
var instance;
return {
getInstance : function() {
if(!instance) {
instance = {
method1: function() {},
method2: function() {}
};
}
return instance;
}
};
})();
 
S

Scott Sauyet

But if i want my `Singleton` inherit from something, I'll be need to
modified my `getInstance' method. I don't want to do it this. In
`getInstance' i want to create only instance properties. I'll be
implement in:

I don't follow this. Do you have an example of how you'd want to use
it?

var Singleton = {};
Singleton.getInstance = function()
{
  this.method1 = function(){};
  this.method2 = function(){};

  this.getInstance = function(){
    return this;
  };
  return this;

};

This doesn't make any sense to me. What is "this" here?

-- Scott
 
S

Scott Sauyet

And I cannot stress this too much: DO NOT do the whole nonsense in these
languages.  You only need the singleton pattern where objects have no
initializer syntax, like in Java.  Implementations of ECMAScript Ed 3.
forward instead allow

  var instance = {
    method1: function() {},
    method2: function() {}
  };

I agree that there is rarely if ever a need for the Singleton pattern
in the classic OO sense here.

But the example above doesn't match one of the OP's requirements:

| Create instance properties when i call `Singleton.getInstance()`

I'm not sure I see much of a reason for this requirement, though,
unless there's some very heavy-weight work going on in the creation of
the instance *and* it fairly frequently is not needed.

-- Scott
 
S

Scott Sauyet

I added var, removed the extra comma, and added a couple of semicolons
that were omitted.

I also removed the null assignment and null check.

The comma was just a cut-and-paste error, but the rest were real
problems in my quicky implementation. Thanks.

-- Scott
 
T

Thomas 'PointedEars' Lahn

Garrett said:

The question is pointless; it simply cannot be done. Every object has a
constructor, even those created with initializers.
This looks more complicated than necessary, but I think would work:

[snip]
It doesn't look complicated at all.
Are there simplifications to be done here?

I added var, removed the extra comma, and added a couple of semicolons
that were omitted.

ACK, AISB. Speaking about Pretty Printing, there should be a space between
the `if' keyword and the opening parenthesis.
I also removed the null assignment and null check.

That is only a partial optimization, though. If this is called the first
time, type conversion from Undefined to Boolean must happen where no type
conversion was necessary before as both operands were of the same type (the
Abstract Equality Comparison Algorithm would have returned in step 3
according to ES3F, and step 1b according to ES5).

If this is called the second time, third time aso., type conversion from
Object to Boolean must happen. This is an optimization because several
type tests were necessary before, as Object is not the same type as Null
(the Abstract Equality Comparison Algorithm would have returned only in the
very last step).

However, if the null assignment was kept and the loose comparison would be
changed into a strict one, which according to my findings is probably safe
by now¹ --

if (instance === null)

--, I think that would be even more efficient (only two type checks and no
type conversion at all).


PointedEars
___________
¹ supported since JavaScript 1.3 (NN 4.06), JScript 5.1.5010 (MSHTML 5),
JSCore 531.9.1 (Safari 4.0.3) or earlier (could not test yet), Opera
5.02, KJS 4.3.4 (Konqueror 4.3.4) or earlier (cannot test this, need to
check source code)
 
A

Asen Bozhilov

Scott said:
I don't follow this.  Do you have an example of how you'd want to use
it?

I wrote in my previous post. If i want to have instance properties in
my Singleton, `getInstance' make a sense for my.
This doesn't make any sense to me.  What is "this" here?

The question is rhetorical? `this' associated with execution context
created when i call `getInstance', refer `object' referred from
`Singleton' from `10.1.7 This`, `11.2.1 Property Accessors` and
`11.2.3 Function Calls` ECMA 262-3 specification.
 
S

Scott Sauyet

I wrote in my previous post. If i want to have instance properties in
my Singleton, `getInstance' make a sense for my.

I think we're having some kind of communication difficulties. It
seems to me that in the code I supplied (preferably with the
improvements from Thomas and Garrett) you can have whatever instance
properties you like; so far we have two functions named "method1" and
"method2", but you can have any additional properties you like.

The question is rhetorical? `this' associated with execution context
created when i call `getInstance', refer `object' referred from
`Singleton' from `10.1.7 This`, `11.2.1 Property Accessors` and
`11.2.3 Function Calls` ECMA 262-3 specification.

No, I understand what "this" represents. I just couldn't figure out
why you'd want to use it here; it seems to muddy the issues.

Right now, with the code you propose, we would have:

var Singleton = {};
Singleton.getInstance = function() {
this.method1 = function(){};
this.method2 = function(){};
this.getInstance = function(){
return this;
};
return this;
};

var x = Singleton.getInstance();
var y = Singleton.getInstance();
var z = new Singleton.getInstance();

window.alert(typeof x.method1); //function
window.alert(typeof x.method2); //function
window.alert(Singleton.getInstance().method1 === x.method1); //
true
window.alert(x === y); //true
window.alert(x === z); //false

That last "false" is probably not what you want, though, correct? And
with the "this", it can get worse:

var w = Singleton.getInstance.call(window);
var x = Singleton.getInstance();

window.alert(x === w); //false
window.alert(typeof window.method1); //function -- OOPS

The other proposal doesn't have these issues, I believe:

var Singleton = (function() {
var instance = null;
return {
getInstance: function() {
if (instance === null) {
instance = {
method1: function() {},
method2: function() {}
};
}
return instance;
}
}
})();

var w = Singleton.getInstance.call(window);
var x = Singleton.getInstance();
var y = Singleton.getInstance();
var z = new Singleton.getInstance();

window.alert(typeof window.method1); //undefined -- CORRECT
window.alert(x === w); //true
window.alert(typeof x.method1); //function
window.alert(typeof x.method2); //function
window.alert(Singleton.getInstance().method1 === x.method1); //
true
window.alert(x === y); //true
window.alert(x === z); //true

So in this case, although you can use Singleton.getInstance as a
constructor, it returns the same object as when used normally. And
you can call it on other objects (such as window) without setting
properties on them. But it's not clear to me what it doesn't do that
you need.

-- Scott
 
R

Richard Cornford

On Jan 26, 2:28 pm, Scott Sauyet wrote:
Right now, with the code you propose, we would have:

var Singleton = {};
Singleton.getInstance = function() {
this.method1 = function(){};
this.method2 = function(){};
this.getInstance = function(){
return this;
};
return this;
};

var x = Singleton.getInstance();
var y = Singleton.getInstance();
var z = new Singleton.getInstance();

window.alert(typeof x.method1); //function
window.alert(typeof x.method2); //function
window.alert(Singleton.getInstance().method1 === x.method1); //
true
window.alert(x === y); //true
window.alert(x === z); //false

That last "false" is probably not what you want, though, correct?

So you sack the nitwit who wrote "new Singleton.getInstance();".
And with the "this", it can get worse:

var w = Singleton.getInstance.call(window);
var x = Singleton.getInstance();

window.alert(x === w); //false
window.alert(typeof window.method1); //function -- OOPS

Remember that javascript is sufficiently flexible that if someone is
trying to break something then they will. Otherwise constructs like
"Singleton.getInstance.call(window)" are not going to randomly appear
in source code, and so in context can only be the products of complete
fools who are better removed from the equation than pandered to.
The other proposal doesn't have these issues, I believe:

var Singleton = (function() {
var instance = null;
return {
getInstance: function() {
if (instance === null) {
instance = {
method1: function() {},
method2: function() {}
};
}
return instance;
}
}
})();

But if you are trying to guard against the random scrubbings of fools
and halfwits what are you going to do to prevent someone re-assigning
a new object with its own - getInstance - method to - Singleton -?
var w = Singleton.getInstance.call(window);
var x = Singleton.getInstance();
var y = Singleton.getInstance();
var z = new Singleton.getInstance();

window.alert(typeof window.method1); //undefined -- CORRECT
window.alert(x === w); //true
window.alert(typeof x.method1); //function
window.alert(typeof x.method2); //function
window.alert(Singleton.getInstance().method1 === x.method1); //
true
window.alert(x === y); //true
window.alert(x === z); //true

So in this case, although you can use Singleton.getInstance as a
constructor, it returns the same object as when used normally.
<snip>

And what type of person is it that uses something that is not a
constructor as a constructor?

Richard.
 
S

Scott Sauyet

But if you are trying to guard against the random scrubbings of fools
and halfwits what are you going to do to prevent someone re-assigning
a new object with its own - getInstance - method to - Singleton -?

No, of course you can't safeguard everything. Asen asked for advice
on how to do something, and specifically asked for

| I want Singleton with properties:
| - Doesn't have constructor

which, as already pointed out, is a strange requirement.

I supplied my answer, which seems not to meet Asen's needs, although I
haven't yet understood the objections. Asen gave some alternative
code. It's not clear to me if it's code that meets the needs or just
a starting point. But if somehow Asen is worried about his code
having spurious constructors, the tests I supplied might help decide
the matter.

-- Scott
 
A

Asen Bozhilov

Scott said:
No, of course you can't safeguard everything.  Asen asked for advice
on how to do something, and specifically asked for

I think Richard maintain something other. Unreasonable usage of
provided code. Everything have requirements for proper and optimize
usage. If i have car which fuel is benzine, if i put diesel i cannot
expect from my car to move. Moreover my car will be broken after my
unreasonable usage. Of course my car has user manual with suggestions
for proper usage. Just like code. If code have documentation, i am
expect developers follow documentation and my suggestions about my
code.
| I want Singleton with properties:
| - Doesn't have constructor
which, as already pointed out, is a strange requirement.

I don't have any benefits from constructor function in my `Singleton`.
The whole "nonsense" idea for `getInstance' method, is to create
instances properties, when i explicit call `getInstance' method. That
can be benefit when i don't want to allocate memory for all properties
of my `Singleton` before i use my `Singleton`.

Thanks for responses.
Regards.
 
S

Scott Sauyet

Asen said:
Scott said:
Richard Cornford wrote:
No, of course you can't safeguard everything.  Asen asked for advice
on how to do something, and specifically asked for

I think Richard maintain something other. Unreasonable usage of
provided code. Everything have requirements for proper and optimize
usage. [ ... ] If code have documentation, i am
expect developers follow documentation and my suggestions about my
code.

I do understand that. And I understood it before Richard posted it.
It would be stupid to try to use the code in this manner. But your
list of required properties made it sound as though an exposed
constructor might cause problems. If you were in total control of how
your code is called, there would presumably be no need for that
requirement. That's why I went further with the constructor
examples. If you don't really need that, the differences between the
approach you give and the one I do are as much a matter of style as
anything else, I believe.

I don't have any benefits from constructor function in my `Singleton`.

If it's simply that the constructor is not needed, this probably
shouldn't be listed as a requirement, but left as an implementation
detail.

The whole "nonsense" idea for `getInstance' method, is to create
instances properties, when i explicit call `getInstance' method. That
can be benefit when i don't want to allocate memory for all properties
of my `Singleton` before i use my `Singleton`.

Either technique will perform this. In yours the properties are
stored in the Singleton object, in mine they are stored in the
"instance" variable stored in the closure, but in either case, they
are where you really need them to be, in the result of
Singleton.getInstance();

Cheers,

-- Scott
 
G

Garrett Smith

Asen said:
I think Richard maintain something other. Unreasonable usage of
provided code. Everything have requirements for proper and optimize
usage. If i have car which fuel is benzine, if i put diesel i cannot
expect from my car to move. Moreover my car will be broken after my
unreasonable usage. Of course my car has user manual with suggestions
for proper usage. Just like code. If code have documentation, i am
expect developers follow documentation and my suggestions about my
code.
Not necessarily strange. It might have been that the goal is to hide the
constructor, to prevent two instances of `Singleton` from being created.
I don't have any benefits from constructor function in my `Singleton`.
The whole "nonsense" idea for `getInstance' method, is to create
instances properties, when i explicit call `getInstance' method. That
can be benefit when i don't want to allocate memory for all properties
of my `Singleton` before i use my `Singleton`.
Singleton is appropriate when the program needs at most one.

A factory getInstance method can facilitate that.
 
G

Garrett Smith

Thomas said:
The question is pointless; it simply cannot be done. Every object has a
constructor, even those created with initializers.

Not every object will have constructor.

Even if changed to "Every native object", it would still not be true.

Even if changed to "Every object except the global object," it would
still not be true.

A new'd object automatically gets a [[Prototype]] from the object that
constructed it. The constructor comes from that. The global object's
[[Prototype]] is implementation dependent, so it might have any constructor.

(function(){
var a = [];

function F(){}

var i = new F;
a.push(i.constructor); // F

delete F.prototype.constructor;

// look up prototype chain.
a.push(i.constructor); // Object

delete Object.prototype.constructor;
a.push("constructor" in i); // false

return a;
})();

Results: [F(), Object(), false]

As a bookmarklet:

javascript: alert(function(){var a = [];function F(){}var i = new
F;a.push(i.constructor);delete
F.prototype.constructor;a.push(i.constructor);delete
Object.prototype.constructor;a.push("constructor" in i);return a}())

In the following code:
var i = new Singleton();
i.constructor

The constructor property is resolved up the prototype chain of `i`. If
Object.prototype.constructor has been deleted, then the result is
`undefined`.

javascript: alert([delete Object.prototype.constructor, "constructor" in
{}]);

An object having a constructor isn't a problem. I do not recommend
deleting Object.prototype.constructor. The example code demonstrated
something that is allowed by the language, not to be taken as practical
advice.
 
T

Thomas 'PointedEars' Lahn

Garrett said:
Not every object will have constructor.
True.

Even if changed to "Every native object", it would still not be true.

True, the Global Object makes an exception there. There is no description
in the Specification how it is created; it is simply "created before
control enters any execution context" and then it "is there".
Even if changed to "Every object except the global object," it would
still not be true.

Yes, it would. While maybe not accessible from ECMAScript code, host
objects need to have a constructor somewhere by which they have been
constructed.
A new'd object automatically gets a [[Prototype]] from the object that
constructed it. The constructor comes from that.

No, the constructor needs to exist before.
The global object's [[Prototype]] is implementation dependent, so it
might have any [[constructor. [...]

I was not talking about the `constructor' property. You miss the point.

However, I should have said "every *user-defined* object". I assumed
that to be obvious from the context of the statement and my mentioning
initializers; my mistake.


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,235
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top