Comment créer un espace de noms en JavaScript afin que mes objets et fonctions ne soient pas remplacés par d'autres objets et fonctions portant le même nom? J'ai utilisé ce qui suit:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
Existe-t-il une manière plus élégante ou succincte de procéder?
javascript
namespaces
javascript-namespaces
Scott McKenzie
la source
la source
Réponses:
J'aime ça:
la source
MyApp
, par exempleMyApp.Views.Profile = {}
plutôt queMyApp.users = {}
etMyViews.Profile = {}
. Pas nécessairement qu'il ne devrait y avoir que deux niveaux de profondeur.J'utilise l'approche trouvée sur le site Enterprise jQuery :
Voici leur exemple montrant comment déclarer des propriétés et fonctions privées et publiques. Tout se fait comme une fonction anonyme auto-exécutable.
Donc, si vous voulez accéder à l'un des membres du public, vous iriez
skillet.fry()
ouskillet.ingredients
.Ce qui est vraiment cool, c'est que vous pouvez maintenant étendre l'espace de noms en utilisant exactement la même syntaxe.
Le troisième
undefined
argumentla source
undefined
argument est la source de la variable de valeurundefined
. En travaillant avec des navigateurs plus anciens / standard javascript (ecmascript 5, javascript <1.8.5 ~ firefox 4), la variable de portée globaleundefined
est accessible en écriture, donc tout le monde peut réécrire sa valeur. L'ajout d'un troisième argument supplémentaire que vous ne transmettez pas en fait une valeurundefined
, vous créez donc une étendue d'espace de nomsundefined
qui ne sera pas réécrite par des sources externes.window.skillet = window.skillet || {}
est qu'il permet à plusieurs scripts d'ajouter en toute sécurité au même espace de noms lorsqu'ils ne savent pas à l'avance dans quel ordre ils s'exécuteront. Cela peut être utile si vous souhaitez pouvoir réorganiser arbitrairement vos inclusions de script sans casser votre code, ou si vous souhaitez charger des scripts de manière asynchrone avec l'attribut async et que vous n'avez donc aucune garantie sur l'ordre d'exécution. Voir stackoverflow.com/questions/6439579/…Une autre façon de le faire, que je considère comme un peu moins restrictive que la forme littérale de l'objet, est la suivante:
Ce qui précède est à peu près comme le modèle de module et que cela vous plaise ou non , il vous permet d'exposer toutes vos fonctions en public, tout en évitant la structure rigide d'un objet littéral.
la source
ns().publicFunction()
, c'est ... çans.publicFunction()
marche.new
mot - clé devant lefunction
mot - clé. Fondamentalement, ce qui se passe, c'est qu'il déclare une fonction anonyme (et en tant que fonction, il est également un constructeur), puis il l'invoque immédiatement en tant que constructeur en utilisantnew
. En tant que tel, la valeur finale qui est stockée à l'intérieurns
est une instance (unique) de ce constructeur anonyme. J'espère que cela a du sens.Oui. Par exemple:
alors vous pouvez avoir
la source
var your_namespace = your_namespace = your_namespace || {}
Je le construis normalement dans une fermeture:
Mon style au fil des ans a changé subtilement depuis que j'écris ceci, et je me retrouve maintenant à écrire la fermeture comme ceci:
De cette façon, je trouve l'API publique et l'implémentation plus faciles à comprendre. Considérez la déclaration de retour comme une interface publique pour l'implémentation.
la source
MYNS.subns = MYNS.subns || {}
??var foo = function
etfunction foo
sont similaires, étant privé; en raison de la nature dynamiquement typée de JavaScript, ce dernier est légèrement plus rapide car il saute quelques instructions dans la plupart des pipelines d'interprètes. Avecvar foo
, le système de type doit être invoqué pour savoir quel type est affecté à ladite var, tandis qu'avecfunction foo
, le système de type sait automatiquement que c'est une fonction, donc quelques appels de fonction sont ignorés, ce qui se traduit par moins d'appels d'instructions de processeur commejmp
,pushq
,popq
, etc, ce qui se traduit par un pipeline de processeur plus courte.function foo
syntaxe est plus lisible. Et j'aime toujours ma version.Parce que vous pouvez écrire différents fichiers JavaScript et les combiner ultérieurement ou non dans une application, chacun doit pouvoir récupérer ou construire l'objet d'espace de noms sans endommager le travail des autres fichiers ...
Un fichier peut avoir l'intention d'utiliser l'espace de noms
namespace.namespace1
:Un autre fichier peut vouloir utiliser l'espace de noms
namespace.namespace2
:Ces deux fichiers peuvent vivre ensemble ou séparément sans entrer en collision.
la source
Voici comment Stoyan Stefanov le fait dans son livre sur les modèles JavaScript que j'ai trouvé très bon (il montre également comment il fait des commentaires qui permettent une documentation API générée automatiquement, et comment ajouter une méthode au prototype d'un objet personnalisé):
la source
J'utilise cette approche:
Le code externe peut alors être:
la source
ns = ns || {}
puisse paraître plus défensif, cela peut entraîner d'autres résultats inattendus.Il s'agit d'un suivi du lien de user106826 vers Namespace.js. Il semble que le projet ait été déplacé vers GitHub . C'est maintenant smith / namespacedotjs .
J'utilise cet assistant JavaScript simple pour mon petit projet et jusqu'à présent, il semble être léger mais suffisamment polyvalent pour gérer l'espacement des noms et le chargement des modules / classes. Ce serait formidable si cela me permettait d'importer un package dans un espace de noms de mon choix, pas seulement l'espace de noms global ... soupir, mais c'est d'ailleurs le point.
Il vous permet de déclarer l'espace de noms puis de définir des objets / modules dans cet espace de noms:
Une autre option consiste à déclarer l'espace de noms et son contenu à la fois:
Pour plus d'exemples d'utilisation, consultez le fichier example.js dans la source .
la source
Échantillon:
Vous pouvez éventuellement déclarer une
local
variable,,same
commeself
et affecterlocal.onTimeout
si vous voulez qu'elle soit privée.la source
Vous pouvez déclarer une fonction simple pour fournir des espaces de noms.
la source
Si vous avez besoin de la portée privée:
sinon si vous n'utilisez jamais la portée privée:
la source
Le modèle de module a été initialement défini comme un moyen de fournir à la fois l'encapsulation privée et publique pour les classes en génie logiciel conventionnel.
Lorsque vous travaillez avec le modèle de module, nous pouvons trouver utile de définir un modèle simple que nous utilisons pour commencer à l'utiliser. En voici une qui couvre l'espacement des noms, les variables publiques et privées.
En JavaScript, le modèle de module est utilisé pour émuler davantage le concept de classes de manière à ce que nous puissions inclure à la fois des méthodes publiques / privées et des variables dans un seul objet, protégeant ainsi des parties particulières de la portée globale. Il en résulte une réduction de la probabilité que nos noms de fonctions entrent en conflit avec d'autres fonctions définies dans des scripts supplémentaires sur la page.
Les avantages
pourquoi le modèle de module est-il un bon choix? Pour commencer, c'est beaucoup plus propre pour les développeurs venant d'un arrière-plan orienté objet que l'idée d'une véritable encapsulation, au moins du point de vue JavaScript.
Deuxièmement, il prend en charge les données privées - ainsi, dans le modèle de module, les parties publiques de notre code peuvent toucher les parties privées, mais le monde extérieur est incapable de toucher les parties privées de la classe.
Désavantages
Les inconvénients du modèle de module sont que, comme nous accédons aux membres publics et privés différemment, lorsque nous souhaitons modifier la visibilité, nous devons en fait apporter des modifications à chaque endroit où le membre a été utilisé.
Nous ne pouvons pas non plus accéder aux membres privés dans les méthodes qui sont ajoutées à l'objet ultérieurement . Cela dit, dans de nombreux cas, le modèle de module est encore très utile et lorsqu'il est utilisé correctement, il a certainement le potentiel d'améliorer la structure de notre application.
Le modèle de module révélateur
Maintenant que nous sommes un peu plus familiers avec le modèle de module, jetons un coup d'œil à une version légèrement améliorée - le modèle de module révélateur de Christian Heilmann.
Le motif du module révélateur est né car Heilmann était frustré par le fait qu'il devait répéter le nom de l'objet principal lorsque nous voulions appeler une méthode publique à partir d'une autre ou accéder à des variables publiques. pour objecter la notation littérale des choses qu'il souhaitait rendre publiques.
Le résultat de ses efforts a été un modèle mis à jour où nous définirions simplement toutes nos fonctions et variables dans la portée privée et retournerions un objet anonyme avec des pointeurs à la fonctionnalité privée que nous souhaitions révéler comme publique.
Vous trouverez ci-dessous un exemple d'utilisation du modèle de module révélateur.
Les avantages
Ce modèle permet à la syntaxe de nos scripts d'être plus cohérente. Il indique également plus clairement à la fin du module quelles sont nos fonctions et variables accessibles au public, ce qui facilite la lisibilité.
Désavantages
Un inconvénient de ce modèle est que si une fonction privée fait référence à une fonction publique, cette fonction publique ne peut pas être remplacée si un correctif est nécessaire. En effet, la fonction privée continuera de faire référence à l'implémentation privée et le modèle ne s'applique pas aux membres publics, uniquement aux fonctions.
Les membres d'objets publics qui font référence à des variables privées sont également soumis aux notes de règle sans correctif ci-dessus.
la source
J'ai créé un espace de noms inspiré des modules d'Erlang. C'est une approche très fonctionnelle, mais c'est ainsi que j'écris mon code JavaScript de nos jours.
Il donne à une fermeture un espace de noms global et expose un ensemble défini de fonctions au sein de cette fermeture.
la source
Après avoir porté plusieurs de mes bibliothèques sur différents projets et avoir constamment changé l'espace de noms de niveau supérieur (nommé statiquement), je suis passé à l'utilisation de cette petite fonction d'assistance (open source) pour définir les espaces de noms.
La description des avantages se trouve sur mon blog . Vous pouvez récupérer le code source ici .
L'un des avantages que j'aime vraiment est l'isolation entre les modules en ce qui concerne l'ordre de chargement. Vous pouvez vous référer à un module externe AVANT qu'il ne soit chargé. Et la référence d'objet que vous obtenez sera remplie lorsque le code sera disponible.
la source
J'utilise la syntaxe suivante pour l'espace de noms.
jsfiddle: http://jsfiddle.net/rpaul/4dngxwb3/1/
la source
J'ai 7 ans de retard à la fête, mais j'ai fait pas mal de travail il y a 8 ans:
Il est important de pouvoir créer facilement et efficacement plusieurs espaces de noms imbriqués pour garder une application Web complexe organisée et gérable, tout en respectant l'espace de noms global JavaScript (empêchant la pollution des espaces de noms), et sans encombrer aucun objet existant dans le chemin de l'espace de noms en le faisant. .
De ce qui précède, c'était ma solution vers 2008:
Ce n'est pas la création d'un espace de noms, mais fournit une fonction pour créer des espaces de noms.
Celui-ci peut être condensé en une doublure minifiée:
Exemple d'utilisation:
Ou, comme une seule déclaration:
L'un ou l'autre est alors exécuté comme:
Si vous n'avez pas besoin de prise en charge des navigateurs hérités, une version mise à jour:
Maintenant, je me méfierais de l'exposer
namespace
à l'espace de noms global lui-même. (Dommage que la langue de base ne nous fournisse pas cela!) Donc, je l'utilise généralement moi-même dans une fermeture, comme:Dans une application plus grande, cela ne doit être défini qu'une seule fois au début du chargement d'une page (pour les applications Web clientes). Des fichiers supplémentaires peuvent ensuite réutiliser la fonction d'espace de noms s'ils sont conservés (inclus comme "facultatif" dans ce qui précède). Au pire, si cette fonction est re-déclarée plusieurs fois - ce ne sont que quelques lignes de code, et moins si elle est minifiée.
la source
Je pense que vous utilisez tous trop de code pour un problème aussi simple. Pas besoin de faire un repo pour ça. Voici une fonction sur une seule ligne.
Essayez-le:
la source
J'aime la solution de Jaco Pretorius, mais je voulais rendre le mot clé "this" un peu plus utile en le pointant sur l'objet module / namespace. Ma version de skillet:
la source
Mon modèle préféré est devenu récemment ceci:
Bien sûr, le retour peut être à la fin, mais si seules les déclarations de fonction le suivent, il est beaucoup plus facile de voir de quoi parle l'espace de noms et quelle API est exposée.
Le modèle d'utilisation des expressions de fonction dans de tels cas se traduit par l'impossibilité de savoir quelles méthodes sont exposées sans parcourir tout le code.
la source
namespace.a();
Si vous utilisez un Makefile, vous pouvez le faire.
Je préfère de toute façon utiliser un Makefile une fois que j'arrive à environ 1000 lignes car je peux efficacement commenter de grandes portions de code en supprimant une seule ligne dans le makefile. Il est facile de jouer avec des trucs. De plus, avec cette technique, l'espace de noms n'apparaît qu'une seule fois dans le prélude, il est donc facile de le modifier et vous n'avez pas à le répéter dans le code de la bibliothèque.
Un script shell pour le développement en direct dans le navigateur lors de l'utilisation d'un makefile:
Ajoutez ceci en tant que tâche de création «go» et vous pouvez «créer» pour garder votre build à jour pendant que vous codez.
la source
Tout à fait un suivi de la réponse d'Ionuț G. Stan, mais montrant les avantages du code épuré en utilisant
var ClassFirst = this.ClassFirst = function() {...}
, qui tire parti de la portée de fermeture de JavaScript pour moins d'encombrement de l'espace de noms pour les classes du même espace de noms.Production:
la source
J'ai écrit une autre bibliothèque d'espaces de noms qui fonctionne un peu plus comme les packages / unités dans d'autres langues. Il vous permet de créer un package de code JavaScript et la référence de ce package à partir d'un autre code:
Fichier hello.js
Fichier Example.js
Seul le deuxième fichier doit être inclus dans la page. Ses dépendances (fichier hello.js dans cet exemple) seront automatiquement chargées et les objets exportés à partir de ces dépendances seront utilisés pour remplir les arguments de la fonction de rappel.
Vous pouvez trouver le projet associé dans les packages JS .
la source
Nous pouvons l'utiliser indépendamment de cette manière:
la source
Mon habitude est d'utiliser la fonction myName () comme stockage de propriété, puis var myName comme support de "méthode" ...
Que ce soit assez légitime ou non, battez-moi! Je m'appuie tout le temps sur ma logique PHP et les choses fonctionnent simplement. :RÉ
if (this !== that) myObj.fName1(); else myObj.fName2();
Référence à ceci: JavaScript: création d'objet avec Object.create ()
la source
En JavaScript, il n'y a pas de méthodes prédéfinies pour utiliser les espaces de noms. En JavaScript, nous devons créer nos propres méthodes pour définir les NameSpaces. Voici une procédure que nous suivons dans les technologies Oodles.
Enregistrer un espace de noms Voici la fonction pour enregistrer un espace de noms
Pour enregistrer un espace de noms, il suffit d'appeler la fonction ci-dessus avec l'argument comme espace de noms séparé par
'.'
(point). Par exemple, laissez le nom de votre application est oodles. Vous pouvez créer un espace de noms en suivant la méthodeFondamentalement, il créera votre structure NameSpaces comme ci-dessous dans le backend:
Dans la fonction ci-dessus, vous avez enregistré un espace de noms appelé
"oodles.HomeUtilities"
et"oodles.GlobalUtilities"
. Pour appeler ces espaces de noms, nous créons une variable, c'est-à-dire var$OHU
et var$OGU
.Ces variables ne sont qu'un alias pour intialiser l'espace de noms. Maintenant, chaque fois que vous déclarez une fonction qui vous appartient,
HomeUtilities
vous la déclarerez comme suit:Ci-dessus se trouve l'initialisation du nom de la fonction et elle est placée dans un espace de noms
$OHU
. et d'appeler cette fonction n'importe où dans les fichiers de script. Utilisez simplement le code suivant.De même, avec les autres NameSpaces.
J'espère que cela aide.
la source
JavaScript ne prend pas en charge l'espace de noms par défaut. Donc, si vous créez un élément (fonction, méthode, objet, variable), il devient global et pollue l'espace de noms global. Prenons un exemple de définition de deux fonctions sans espace de noms,
Il appelle toujours la deuxième définition de fonction. Dans ce cas, l'espace de noms résoudra le problème de collision de noms.
la source