-
-
Save dmnsgn/4a6ad76de1b5928f13f68f406c70bb09 to your computer and use it in GitHub Desktop.
class SingletonDefaultExportInstance { | |
constructor() { | |
this._type = 'SingletonDefaultExportInstance'; | |
} | |
singletonMethod() { | |
return 'singletonMethod'; | |
} | |
static staticMethod() { | |
return 'staticMethod'; | |
} | |
get type() { | |
return this._type; | |
} | |
set type(value) { | |
this._type = value; | |
} | |
} | |
export default new SingletonDefaultExportInstance(); | |
// ... | |
// index.js | |
import SingletonDefaultExportInstance from './SingletonDefaultExportInstance'; | |
// Instantiate | |
// console.log(new SingletonDefaultExportInstance); // is not a constructor | |
// Prototype Method | |
console.log(SingletonDefaultExportInstance.type, SingletonDefaultExportInstance.singletonMethod()); | |
// Getter/Setter | |
SingletonDefaultExportInstance.type = 'type updated'; | |
console.log(SingletonDefaultExportInstance.type); | |
// Static method | |
console.log(SingletonDefaultExportInstance.constructor.staticMethod()); |
Be careful with this, because it's not a "true" singleton. It relies on the require cache for "singleton-ness", which isn't reliable.
For example, requiring the file above as require('./SingletonDefaultExportInstance')
will result in a different instance of the module from require('./singletondefaultexportInstance')
(assuming a case insensitive file-system).
@jasonkarns - so how do you export TRUE TRUE singleton?
Yes, would be good to discuss :) Also for others coming across this later.
IMHO, case insensitivity seems like it should be a bug with require's implementation if you're actually able to import a package that way.
it also fails as a singleton if you have two copies of the package, for example in a mono repo where packages can have their own node_modules
This is part of a series on Singletons, if you are looking for different ways of implementing it: https://medium.com/@dmnsgn/singleton-pattern-in-es6-d2d021d150ae
@codewithcheese You could work around the issue and store instances even more "global" and use globalThis
(works on Node and Browser)
// a.js
export class A {
constructor(){
console.log('A constructor()')
}
static get instance() {
return (globalThis[Symbol.for(`PF_${A.name}`)] ||= new this());
}
}
// index.js
import { A } from './a.js';
console.log('A.instance', A.instance);
console.log('A.instance', A.instance);
Or if you do not want to export A
and just the single instance:
// a.js
class A { // <- no export here
// same code
}
const {instance} = A; // destruct `static get instance`
export {
instance // ... and export instance. (optional re-naming if you do not want to import something called "instance"
}
As a named export:
or if you want to export as the class' name: