In the world of JavaScript, design patterns are your secret weapon to crafting efficient, organized, and maintainable code. Among these patterns, t...
For further actions, you may consider blocking this person and/or reporting abuse
Actually in JS, any ES module is a singleton ! No need for getInstance() or any other fancy OOP stuff 😅
Was about to say the same thing.
You beat me to it!
To expand on what others are saying regarding ES modules being singletons: what this means is that every module you load in your program is only evaluated once.
So, while you can import a module multiple times, any code that's executed within its immediate scope only runs on the first import.
In your example, the way you would implement
Logger
as singleton is to just export an instance of the class:This guarantees that will only ever be one instance of
Logger
per process.Consider this application structure:
When we run
index.mjs
this is the output:As you can see, all logs are sent to the same instance and modules are only evaluated the first time they're imported.
Thank you for your very good explanation!
You're very welcome. I felt like "JS module is a singleton" isn't really an answer, and this fact doesn't make the singleton pattern redundant.
Exploiting JS module singleton is fine if you have a simple, single use case that doesn't require configuration. But if you have different implementations or use case requirements, then defining a singleton would be required.
An example of this in an Electron app I'm working on is handling IPC events when there are multiple render processes that need to handle events. Events need to be handled sequentially for each render process so I need some kind of queue system.
It's possible to achieve this with a JS module singleton. But it requires complex logic to determine which render process to delegate handling.
There's a lot of problems here and this control flow needs to exist on any method that interacts with render processes. It will get messy pretty quickly.
It's much simpler to just define a singleton that accepts the render process and reference this instead:
So yeah, the fact that JS modules are singletons doesn't eliminate the need for singleton patterns in modular JS programs :)
In your exemple nothing prevent 2 instance of the logger class which is the heart of the singleton "pattern".
Moreover your variable holding the instance reference is public hence the risk of letting the anyone resetting it to null.
A more secure approch could be :
Instance is private to the class , constructor will throw an error if an other instance exists
Very interesting approach, thank's for your feedback :)
If es modules are used, we wouldn't even need to worry about multiple instances being created, we could just:
export const logger = new Logger();
I agree with @grunk comment, and we should make the
access modifier
ofconstructor
is private to prevent new classUnfortunately you can't in JS 😉
If there are multiple methods that we can execute as part of the logging mechanism then probably a class approach like in the example would be a good solution vs just es modules, that way its more explicit
Very interesting thanks!
I appreciate all the ESM comments, but I have a usecase where I create named logger instances.
So I call
const logger = loggerFactory('MyService');
and behind that I have aMap<string, Logger>