Understanding the fact that singleton creates a shared global state, there will be situations where I might want singleton such as redux store/state object.
If I am using ES modules, I can use the simple code as follows to create singleton:
// a.js (singleton module)class A {}
// Create singletonexport const a = new A();
Now I can use this instantiated object anywhere in another modules:
// b.js// Import singletonimport { a } from './a.js';
console.log(a);
// c.js - some other nested fileimport { a } from '../../a.js';
console.log(a);
In theory, it should be possible to manage singleton creation as described above. But as of today, we use module bundlers like Webpack.js or Rollup.js to serve JavaScript to the browser. What if these bundlers accidentally/intentionally include some module more than once. The simplest possible thing I can imagine is if I have some sort of symlinks that resolves to the same module via different paths. Or it could simply be a bug in module resolution process.
My question is - do these module bundlers always ensure that a module creating a singleton object stays singleton under every circumstance?
There is one topic which I have not fully looked into. I know ES Symbols are globally unique and they are used to create private object members. That is my next question - Is there a way this characteristics of the symbol can help me create a true singleton? (I believe that symbols will suffer the same problem if bundling process is not sound.)
Finally, last question: Is it ever possible to reliably create a true singleton in JavaScript?
Note: I am not trying to guard against a bug in Module bundler. Bug analogy just is a figure of speech to illustrate the idea.
In general, module bundlers like Webpack and Rollup do not guarantee that a module creating a singleton object will stay a singleton under every circumstance. If the bundler includes a module more than once, for example due to a bug in the module resolution process or due to the use of symlinks that resolve to the same module via different paths, then the singleton pattern may not work as intended.
One way to create a true singleton in JavaScript is to use the approach you mentioned, where you define the singleton class and create a single instance of it in a separate module, and then export the instance so that it can be imported and used by other modules. However, as mentioned earlier, this approach is not foolproof and may not work in all cases.
Another way to create a singleton in JavaScript is to use the Symbol type to define a unique symbol that can be used as a private property of the singleton class. This approach can help ensure that the singleton instance is unique and cannot be accessed or modified by other code. However, like the first approach, this method is not foolproof and may not work in all cases.
In general, it may not be possible to reliably create a true singleton in JavaScript, especially if the code is being bundled by a module bundler. There are many factors that can affect the behavior of singletons in JavaScript, and it may be difficult to anticipate and account for all of them. It is generally a good idea to use caution when implementing singletons in JavaScript and to consider whether they are truly necessary for your application.