Espace de noms JavaScript

Je veux créer un espace de noms global pour ma demande et dans cet espace de noms je souhaite d'autres espaces de noms:

Par exemple

Dashboard.Ajax.Post() Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent(); 

Je veux aussi les placer dans des fichiers séparés:

  • Ajax.js
  • RetrieveContent.js

Cependant, j'ai essayé d'utiliser cette méthode, mais cela ne fonctionnera pas car le même nom de variable est utilisé pour l'espace de noms dans 2 endroits séparés. Quelqu'un peut-il proposer une alternative?

Merci.

Il suffit de vous assurer que vous ne piétiniez pas sur votre objet de namespace s'il était déjà créé. Quelque chose comme ça fonctionnerait:

 (function() { // private vars can go in here Dashboard = Dashboard || {}; Dashboard.Ajax = { Post: function() { ... } }; })(); 

Et le fichier RetrieveContent serait défini de manière similaire.

Voici un très bon article sur divers «Patterns de module» en JavaScript. Il existe une très jolie petite section sur la façon dont vous pouvez augmenter les modules, ou les espaces de noms et de maintenir un état privé en mode croisé. C'est-à-dire que le code dans des fichiers séparés sera exécuté séquentiellement et augmentera correctement l'espace de noms après son exécution.

Je n'ai pas exploré cette technique à fond, donc pas de promesses … mais voici l'idée de base.

Tableau de bord.js

 (function(window){ var dashboard = (function () { var my = {}, privateVariable = 1; function privateMethod() { // ... } my.moduleProperty = 1; my.moduleMethod = function () { // ... }; return my; }()); window.Dashboard = dashboard; })(window); 

Dashboard.ajax.js

 var dashboard = (function (my) { var _private = my._private = my._private || {}, _seal = my._seal = my._seal || function () { delete my._private; delete my._seal; delete my._unseal; }, _unseal = my._unseal = my._unseal || function () { my._private = _private; my._seal = _seal; my._unseal = _unseal; }; // permanent access to _private, _seal, and _unseal my.ajax = function(){ // ... } return my; }(dashboard || {})); 

Dashboard.retrieveContent.js

 var dashboard = (function (my) { var _private = my._private = my._private || {}, _seal = my._seal = my._seal || function () { delete my._private; delete my._seal; delete my._unseal; }, _unseal = my._unseal = my._unseal || function () { my._private = _private; my._seal = _seal; my._unseal = _unseal; }; // permanent access to _private, _seal, and _unseal my.retrieveContent = function(){ // ... } return my; }(dashboard || {})); 

La fonction Yahoo Namespace est exactement conçue pour ce problème.

Ajoutée:

La source de la fonction est disponible. Vous pouvez le copier dans votre propre code si vous le souhaitez, changer la racine de YAHOO à autre chose, etc.

Il existe plusieurs bibliothèques qui offrent déjà ce type de fonctionnalité si vous souhaitez utiliser ou examiner une solution pré-cuite (c'est-à-dire testée).

  • YUI.attribute et YUI.base
  • Dojo.mixin
  • Underscore.extend
  • JQuery.extend
  • Goog.provide et goog.object.extend

L' jQuery.extend plus simple et la plus jQuery.extend pour se lancer est probablement jQuery.extend , l'argument deep défini. (La raison pour laquelle je dis qu'il est sans bug n'est pas parce que je pense que jQuery.extend souffre de moins de bogues que n'importe quelle autre bibliothèque, mais parce qu'elle offre une option claire aux attributs de copie profonde de l'expéditeur au destinataire – ce qui La plupart des autres bibliothèques ne fournissent pas explicitement . Cela empêchera de nombreux bugs difficiles à diagnostiquer de se lancer dans votre programme plus tard parce que vous avez utilisé une extend peu profonde et que vous avez maintenant des fonctions s'exécutant dans des contextes que vous ne vous attendiez pas à En cours d'exécution. (Si toutefois vous êtes conscient de la façon dont vous étendez votre bibliothèque de base lors de la conception de vos méthodes, cela ne devrait pas poser de problème).

Avec l'objet NS créé, vous devriez pouvoir y ajouter n'importe où. Bien que vous souhaitiez essayer var NS = NS || {}; var NS = NS || {}; Pour s'assurer que l'objet NS existe et n'est pas écrasé.

 // NS is a global variable for a namespace for the app's code var NS = NS || {}; NS.Obj = (function() { // Private vars and methods always available to returned object via closure var foo; // ... // Methods in here are public return { method: function() { } }; }()); 

Vous pourriez faire quelque chose comme ça …

Page HTML utilisant la bibliothèque de zones de noms:

 <html> <head> <title>javascript namespacing</title> <script src="dashboard.js" type="text/javascript"></script> <script src="ajax.js" type="text/javascript"></script> <script src="retrieve_content.js" type="text/javascript"></script> <script type="text/javascript"> alert(Dashboard.Ajax.Post()); alert(Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent()); Dashboard.RetrieveContent.Settings.Timeout = 1500; alert(Dashboard.RetrieveContent.Settings.Timeout); </script> </head> <body> whatever... </body> </html> 

Dashboard.js:

 (function(window, undefined){ var dashboard = {}; window.Dashboard = dashboard; })(window); 

Ajax.js:

 (function(){ var ajax = {}; ajax.Post = function() { return "Posted!" }; window.Dashboard.Ajax = ajax })(); 

Retrieve_Content.js:

 (function(){ var retrieveContent = {}; retrieveContent.RefreshSalespersonPerformanceContent = function() { return "content retrieved" }; var _contentType; var _timeout; retrieveContent.Settings = { "ContentType": function(contentType) { _contentType = contentType; }, "ContentType": function() { return _contentType; }, "Timeout": function(timeout) { _timeout = timeout; }, "Timeout": function() { return _timeout; } }; window.Dashboard.RetrieveContent = retrieveContent; })(); 

Le tableau de bord.js agit comme point de départ pour tous les espaces de noms sous celui-ci. Le reste est défini dans leurs fichiers respectifs. Dans Retrieve_Content.js, j'ai ajouté quelques propriétés supplémentaires dans Settings pour donner une idée de la façon de le faire, si nécessaire.

Je crois que le modèle de module pourrait être juste dans votre allée. Voici un bon article concernant différents modèles de modules.

http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

Je vous recommande vivement d'utiliser cette technique:

https://github.com/mckoss/namespace

  namespace.lookup('com.mydomain.mymodule').define(function (ns) { var external = namespace.lookup('com.domain.external-module'); function myFunction() { ... } ... ns.extend({ 'myFunction': myFunction, ... }); }); 

J'ai utilisé ce modèle depuis quelques années; J'aimerais que davantage de bibliothèques fassent la même chose; Il m'a été beaucoup plus facile de partager du code sur mes différents projets.

J'ai écrit cette fonction pour simplifier la création d'espaces de noms. Mabey, cela vous aidera.

 function ns(nsstr) { var t = nsstr.split('.'); var obj = window[t[0]] = window[t[0]] || {}; for (var i = 1; i < t.length; i++) { obj[t[i]] = obj[t[i]] || {}; obj = obj[t[i]]; } } ns('mynamespace.isawesome.andgreat.andstuff'); mynamespace.isawesome.andgreat.andstuff = 3; console.log(mynamespace.isawesome.andgreat.andstuff); 

Bob.js peut aider à définir vos espaces de noms (entre autres):

 bob.ns.setNs('Dashboard.Ajax', { Post: function () { /*...*/ } }); bob.ns.setNs('Dashboard.RetrieveContent', { RefreshSalespersonPerformanceContent: function () { /*...*/ } }); 

La mise en oeuvre:

 namespace = function(packageName) { // Local variables. var layers, layer, currentLayer, i; // Split the given string into an array. // Each element represents a namespace layer. layers = packageName.split('.'); // If the top layer does not exist in the global namespace. if (eval("typeof " + layers[0]) === 'undefined') { // Define the top layer in the global namesapce. eval(layers[0] + " = {};"); } // Assign the top layer to 'currentLayer'. eval("currentLayer = " + layers[0] + ";"); for (i = 1; i < layers.length; ++i) { // A layer name. layer = layers[i]; // If the layer does not exist under the current layer. if (!(layer in currentLayer)) { // Add the layer under the current layer. currentLayer[layer] = {}; } // Down to the next layer. currentLayer = currentLayer[layer]; } // Return the hash object that represents the last layer. return currentLayer; }; 

Résultat:

 namespace('Dashboard.Ajax').Post = function() { ...... }; namespace('Dashboard.RetrieveContent').RefreshSalespersonPerformanceContent = function() { ...... }; 

Essentiel:

Namespace.js