This implementation is slightly tricky: MySingletonClass
acts as a function, an object, and a constructor in different contexts. Also the constructor sometimes returns a different object, instead of modifying this
as usual.
The singleton object is stored as a property of the function MySingletonClass
i.e. MySingletonClass._singletonInstance
.
MySingletonClass
is called as either a function (MySingletonClass()
) or a constructor (new MySingletonClass()
). When it is called, the object may or may not already exist. Let's look at these cases:
Constructor - Object exists
arguments.callee
is just the function so you could use MySingletonClass._singletonInstance
instead. The first line checks if the object exists, and then the second returns it. Because an object is returned from the constructor, the result of the new expression is that object.
Constructor - Object does not exist
The singleton object is set to this
, the object that is currently being constructed, and then this
is initialized by adding some functions (Foo
etc). The call to the constructor then evaluates to this
. The object now exists so it won't be initialized again.
Function - Object exists
arguments.callee
is still the function so the object is returned as before.
Function - Object does not exist
Here, this
is the global object, so the _singletonInstance
variable and the Foo
functions are added to the global object. The function doesn't return anything so b
becomes undefined
. This is not the behavior you want.
In the first three cases, the object MySingletonClass._singletonInstance
is initialized if it doesn't exist, and then the calling expression evaluates to that instance.
As for multiple instances, it wouldn't make much sense to create multiple instances of a singleton. How would you specify which instance to get? If you want multiple instances, just remove the arguments.callee
code at the beginning and you have a non-singleton constructor.