It’s impossible to create a Singleton in Javascript, given the prototypical nature of the language. The vast majority of object-oriented languages use what we call OO Classical, in which class inherits from class and object instance class:
classe A <== classe B (herda de A - sua "superclasse")
^ ^
| |
objeto 1 objeto 2 (não herda de objeto 2 - não diretamente, pelo menos)
Already in the O Prototypic, there are no classes, and object inherits from object:
objeto 1 <== objeto 2 (herda de objeto 1 - seu "protótipo")
Javascript (in its current version) has prototype semantics only, but a bizarre syntax that makes seem that it implements Classical OO, when in fact this does not occur:
function A() { this.foo = 10; }
var objeto1 = new A();
function B() { this.bar = 20; }
B.prototype = new A(); // Vou chamar esse objeto de "anônimo"; poderia ser o próprio objeto1
var objeto2 = new B();
It seems that the "class" B inherited from A, and the objects "instantiated the class", right? But the above code could also be written as follows:
var objeto1 = { foo:10 };
var objeto2 = Object.create({ foo:10 }, { bar:{ value:20 } }); // anônimo poderia ser objeto1
In both cases, anônimo
is the prototype of objeto2
. This means any read type access objeto2.foo
will first see if there is the property foo
in objeto2
and, if it does not exist, it will return anônimo.foo
. Already in a script, it will create this property in objeto2
if it does not exist (or will update if it already exists). You can read more about how prototypes work in this related question.
The consequence of this, however, is that if you have a reference to one object nothing prevents you from creating another that inherits [prototypically] from it:
var xyz = xyz || (function (){ // Essa função só será chamada uma única vez, garantidamente
this.foo = function() { ... };
})();
var abc = Object.create(xyz, { bar:{ value:20 } }); // Mas agora abc herda de xyz
abc.foo(); // Chamou o método foo de xyz, usando abc como this!
Although xyz
be it immutable, or has "prohibited extensions" via Object.preventExtensions
or Object.seal
, None of that prevents him from being inherited. If there is a way to mark an object as "it is forbidden to use it as a prototype of other objects", I do not know. Just stopping others from getting a reference for him...
Finally, if it was not clear, creating an "empty" object inherited from another would be the same as "creating another instance of your class". Because all the methods of the first are available to be called, and the new object has a copy of all its properties - it can change them or not. If any method of the ancient object assumes that it will always be called using xyz
as this
, call him via abc
will violate this premise and may have negative consequences. That is: do not assume that a Javascript object is guaranteed Singleton.
I’m not sure what you’re looking for (I think it’s because of the example; usually, Singleton simulacrats in JS use
new
). I don’t know if it helps, but I usually recommend using a literal object instead of trying to simulate singletons. Solves some use cases, probably not all.– bfavaretto
Poise, I forgot to comment on this in question. If with the global literal objects, I have need of Singleton.
– Andre Figueiredo