Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use module as singleton

In javascript we can use module as singleton.

//a.js
export default {str:'aaa'}

//b.js
import singleton from 'a.js'
singleton.str='bbb'

//c.js
import singleton from 'a.js'
singleton.str='ccc'

I want to use it to be the configure of my module. Is there any risk? It will always be a singleton in every module system?

like image 322
lei li Avatar asked Oct 22 '20 07:10

lei li


People also ask

Can modules singleton?

In javascript we can use module as singleton.

Is a Python module a singleton?

Modules are “singletons” in Python because import only creates a single copy of each module; subsequent imports of the same name keep returning the same module object.

Is module exports a singleton?

}module. exports = Singleton; As we can see we actually created two classes PrivateSingleton and Singleton . This is a trick to hide (create pseudo-private) constructor in Singleton class.

Why we should not use singleton?

By using singletons in your project, you start to create technical debt. Singletons tend to spread like a virus because it's so easy to access them. It's difficult to keep track of where they're used and getting rid of a singleton can be a refactoring nightmare in large or complex projects.


Video Answer


1 Answers

I want to use it to be the configure of my module. Is there any risk? It will always be a singleton in every module system?

Yes, an ESM module (and a commonjs module) is guaranteed to return the same instance. **

While this is bad design (because it's mutable global state anyone can import and change and it's hard to keep track of) - it's entirely guaranteed to always work.

If you're interested in the details of how Node.js loads modules - you can see the reference of the resolver algorithm in our docs and the relevant bits for CommonJS here.


This is safe to rely on. I'll try to explain why. Imagine modules didn't work this way:

//a.js
export default class Foo { /* some code */ }

//b.js
import Foo from './a';

If whenever b and other files import the class Foo they might get a different instance - stuff like instanceof wouldn't work across modules and it would be impossible to rely on references.

This is generally why this is both guaranteed and supported.

As a fun side node - ES Modules are live references :]

**the caveat is that it's possible to "opt out" - for example by deleting the module from require.cache and setting require.parent in commonjs. However, this is never the default behavior.

like image 178
Benjamin Gruenbaum Avatar answered Nov 10 '22 14:11

Benjamin Gruenbaum