Déclaration d'espace de noms Javascript avec prototype de fonction

Je sais, cela est souvent discuté. Mais après avoir cherché comme une personne du 19ème siècle, j'ai besoin de conseils. Je n'ai aucun problème en déclarant un «espace de noms», mais quand il s'agit d'une fonction prototype.foo, j'ai collé. J'ai trouvé un moyen, mais je ne l'aime pas:

Namespace = {} Namespace.obj = function() { this.foo="bar"; } Namespace.obj.prototype.start = function() { this.foo="fubar"; } blah = new Namespace.obj(); blah.start(); 

Maintenant, puisque je suis un peu névrosé en cas de script, j'aimerais avoir quelque chose comme ça:

 Namespace = { obj: function() { this.foo="bar"; }, obj.prototype.start: function(tabinst) { this.foo="fubar"; } } ... 

Mais alors, il lance une erreur: "Sincette d'erreur non détectée: jeton inattendu".

Je sais, c'est cosmétique, mais je pense qu'il doit y avoir une meilleure méthode pour déclarer un «espace de noms» contenant des fonctions de classe et de prototype.

La façon dont je le ferais utilise le «modèle de module» .
Vous encapsulez essentiellement toute votre logique "Module" dans une fonction d'auto-exécution qui renverrait un objet ayant vos classes, fonctions, variables, etc. … Pensez à la valeur de retour en exposant votre API de module.

 Namespace = (function () { /** Class obj **/ var obj = function () { this.foo = 'bar'; }; obj.prototype = { start: function () { this.foo = 'fubar'; } }; /** Class obj2 **/ var obj2 = function () { this.bar = 'foo' }; obj2.prototype = { start: function () { this.bar = 'barfoo'; }, end: function () { this.bar = ''; } }; return { obj : obj, obj2: obj2 }; })(); var o = new Namespace.obj() o.start() 

Afin d'encapsuler davantage les méthodes et constructeurs de classe "obj", nous pourrions faire ce qui suit:

 /** Class obj **/ var obj = (function () { /** class Constructor **/ var obj = function () { this.foo = 'bar'; }; /** class methods **/ obj.prototype = { start: function () { this.foo = 'fubar'; } }; return obj; })(); 

Il existe également une fonctionnalité importante qui vient gratuitement en utilisant ce modèle, qui est "Variables privées", considérez ce qui suit:

 /** Class Foo **/ var Foo = (function () { // Private variables var private_number = 200 /** class Constructor **/ var Foo = function () { this.bar = 0; }; /** class methods **/ Foo.prototype = { add: function () { this.bar += private_number; } }; return Foo; })(); foo = new Foo(); alert(foo.bar); // 0 foo.add(); alert(foo.bar);// 200 alert(foo.private_number) //undefined 

Oui, parce que vous ne pouvez pas utiliser ce type de chaînage dans une déclaration d'objet

Obj.prototype ou obj.something here, car la langue voit obj comme une valeur non-objet. Vous pouvez fausser un tel effet comme celui-ci

 Namespace = {}; Namespace.obj =function() { this.foo="bar"; }; Namespace.obj.prototype.start = function(tabinst) { this.foo="fubar"; }; console.log( Namespace.obj.prototype ); 

(Voir cette violon http://jsfiddle.net/WewnF/ )

EDIT: Wow, j'ai juste remarqué que ce que je disais était déjà dans la question. Je suis tellement désolé de ne pas le remarquer plus tôt … Eh bien, la façon dont vous vous êtes décrit est la méthode correcte pour y parvenir.

Sinon, vous pouvez réécrire votre code comme celui-ci – mais ce n'est pas exactement ce que vous avez suivi et ne fonctionnera pas (puisque obj ne sera pas une fonction elle-même et vous devrez appeler sa fonction principale comme ceci obj. principale(); )

 Namespace = { obj: { main : function() { this.foo="bar"; }, prototype : { start: function(tabinst) { this.foo="fubar"; } } } } 

EDIT 2: Voir cette violon http://jsfiddle.net/NmA3v/1/

 Namespace = { obj: function() { this.foo="bar"; }, prototype: { obj : { start : function( hi ) { alert( hi ); } } }, initProto : function(){ for( var key in Namespace ) { if( key !== "prototype" ) { for( var jey in Namespace.prototype[ key ] ) Namespace[ key ].prototype[ jey ] = Namespace.prototype[ key ][ jey ]; } } } } Namespace.initProto(); console.log( Namespace.obj); var test = new Namespace.obj(); test.start( "Hello World" ); 

Cela aura exactement le même effet. Explication: nous déclarons nos objets comme des propriétés-fonctions normales, puis utilisons un objet prototype maître qui conteneur des objets avec les mêmes noms que ci-dessus, par exemple pour chaque espace de noms.obj, il existe également un espace de noms.prototype.obj qui contient le Fonctions que nous voulons ajouter à la chaîne prototype.

Puis avec namespace.protoInit (), nous itérons à travers toutes les propriétés – et extraire les fonctions à partir de Namespace.prototype [clé] et les ajouter à l'espace de noms [clé] .prototype – étendre avec succès l'objet prototype! Un peu peu orthodoxe, mais fonctionne!

Juste pour les coups de pied et pour élargir la réponse ci-dessus. Un peu plus de notation d'objet orientée en fonction de l'espace de noms imbriqué

 var NS = {}; // Class List NS.Classes = { Shape: (function(){ // Private var whateveryouwishboss = false; // Public var Shape = function(x,y,w,h){ this.x = x; this.y = y; this.w = w; this.h = h; }; Shape.prototype = { draw: function(){ //... Im on prototype Shape } } return Shape; })(), Person: (function(){ //.... })() } /////// Let the games begin var rect = new NS.Class.Shape(0,0,10,10); rect.draw()