3

Let's say we have 2 js modules (A, B) that require a common module 'C' which is a Singleton or has static methods. If they both require the same instance of C then everything is fine. But if for some reason the require method will resolve to different files (for example, if they require different versions or if the C module was bundled inside one of them) then we will have 2 different instances of C, even though it is setup as a singleton.

How can we force the singleton patter in javascript even when the code can exist twice? Can I use the global namesapce, or are there any better patterns? If so, how do I use global correctly?

Kristianmitk
  • 4,528
  • 5
  • 26
  • 46
S.Kraus
  • 369
  • 4
  • 13

1 Answers1

1

It seems that using the global scope is the only way, but there are ways to make this safer using symbols.

// create a unique, global symbol name
// -----------------------------------

const FOO_KEY = Symbol.for("My.App.Namespace.foo");

// check if the global object has this symbol
// add it if it does not have the symbol, yet
// ------------------------------------------

var globalSymbols = Object.getOwnPropertySymbols(global);
var hasFoo = (globalSymbols.indexOf(FOO_KEY) > -1);

if (!hasFoo){
  global[FOO_KEY] = {
    foo: "bar"
  };
}

// define the singleton API
// ------------------------

var singleton = {};

Object.defineProperty(singleton, "instance", {
  get: function(){
    return global[FOO_KEY];
  }
});

// ensure the API is never changed
// -------------------------------

Object.freeze(singleton);

// export the singleton API only
// -----------------------------

module.exports = singleton;

Based on a tutorial found here

S.Kraus
  • 369
  • 4
  • 13