Pattern Singleton avec Browserify / CommonJS

Essayer de mettre en œuvre le modèle singleton dans les modules CommonJS, en utilisant Browserify. Jusque là:

// foo.js

var instance = null; var Foo = function(){ if(instance){ return instance; } this.num = 0; return instance = new Foo(); } Foo.prototype.adder = function(){ this.num++; }; module.exports = Foo(); 

// main.js

 var foo = require('./foo.js'); console.log(foo.num); // should be 0 foo.adder(); // should be 1 var bar = require('./foo.js'); console.log(bar.num); // like to think it'd be 1, not 0 

Le premier problème est que je reçois une erreur de maximum call stack exceeded lorsque je charge le fichier JS intégré dans le navigateur, mais deuxièmement, est-ce que je m'approche correctement? Est-ce possible?

Le premier problème, c'est que je reçois une erreur d'erreur maximale dépassée

Eh bien, cela vient de votre fonction Foo appelant new Foo

Mais deuxièmement, est-ce que je m'approche correctement?

Non. Pour les singletons, vous n'avez pas besoin d'une «classe» avec un constructeur et un prototype – il n'y aura qu'une seule instance. Créez simplement un objet, plus facilement avec un littéral, et renvoyez ceci:

 module.exports = { num: 0, adder: function(){ this.num++; } }; 

Le résultat d'un appel requis est un singleton, qu'il s'agisse d'une instance singleton ou d'une fonction singleton ou d'une seule usine. En outre, un appel obligatoire doit être idempotent – les modules CommonJS mal écrits peuvent en être le cas, donc si un module CommonJS a un effet secondaire, cet effet secondaire devrait se produire une seule fois, peu importe combien de fois cela nécessite.

L'extrait de code que vous avez

 if(instance){ return instance; } // ... return instance = new Foo(); 

Est un héritage des types de cercles que vous devriez sauter si vous utilisiez un ancien JavaScript simple pour créer des singletons. Il est totalement inutile lors de l'utilisation de CommonJS et, en plus, cela entraîne maximum call stack exceeded problème de maximum call stack exceeded .

Votre code pourrait être réécrit comme ceci:

 var Foo = function(){ this.num = 0; } Foo.prototype.adder = function(){ this.num++; }; module.exports = new Foo(); 

Ou encore plus succinctement:

 module.exports = { num: 0, adder: function(){ this.num++; } } 

Parce que mettre la méthode adder sur le prototype ne vous procure aucune efficacité réelle si vous ne créez qu'une seule instance de Foo et que vous n'avez pas besoin de cacher quelque chose dans la fermeture.