La programmation modulaire est un modèle de programmation JavaScript très commun. Cela peut généralement rendre le code plus facile à comprendre, mais il existe de nombreuses excellentes pratiques qui ne sont pas bien connues.
Base
Décrivons d'abord brièvement certains modèles modulaires depuis qu'Eric Miraglia (le développeur de YUI) a publié pour la première fois un blog il y a trois ans décrivant des modèles modulaires. Si vous connaissez déjà très bien ces modes modulaires, vous pouvez ignorer cette section directement et commencer à lire à partir du "mode avancé".
Fermeture anonyme
Il s'agit d'une structure de base qui rend tout possible, et c'est aussi la meilleure caractéristique de JavaScript. Nous allons simplement créer une fonction anonyme et l'exécuter immédiatement. Tout le code s'exécutera dans cette fonction et vivra dans une fermeture qui fournit une privatisation, ce qui suffit pour permettre aux variables de ces fermetures de passer toute la vie de notre application.
La copie de code est la suivante:
(fonction () {
// ... Tous les Vars et fonctions sont dans cette portée uniquement
// maintient toujours l'accès à tous les globaux
} ());
Remarquez les supports les plus extérieurs de cette paire enroulant des fonctions anonymes. En raison des caractéristiques linguistiques de JavaScript, cela est nécessaire pour les supports. Les instructions commençant par la fonction de mot-clé dans JS sont toujours considérées comme déclaratives de fonction. Enveloppez ce code entre parenthèses pour faire savoir à l'interprète qu'il s'agit d'une expression de fonction.
Importation variable globale
JavaScript a une fonctionnalité appelée variables globales implicites. Peu importe lorsqu'un nom de variable est utilisé, l'interprète trouvera l'instruction de déclaration VAR de la variable à l'envers en fonction de la chaîne de portée. Si l'instruction de déclaration VAR n'est pas trouvée, cette variable sera considérée comme une variable globale. Si cette variable est utilisée dans une instruction d'affectation et que la variable n'existe pas, une variable globale sera créée. Cela signifie qu'il est facile à utiliser ou à créer des variables globales dans les fermetures anonymes. Malheureusement, cela rend le code écrit extrêmement difficile à maintenir, car pour les sentiments intuitifs des gens, il est impossible de dire en un coup d'œil que ces variables sont mondiales.
Heureusement, nos fonctions anonymes fournissent des solutions de contournement simples. Il suffit de passer la variable globale en tant que paramètre dans notre fonction anonyme, vous pouvez obtenir un code plus clair et plus rapide que la variable globale implicite. Voici un exemple:
La copie de code est la suivante:
(fonction ($, yahoo) {
// a maintenant accès à Globals jQuery (comme $) et yahoo dans ce code
} (jQuery, yahoo));
Exportation du module
Parfois, vous voulez non seulement utiliser des variables globales, mais vous souhaitez également les déclarer pour une utilisation répétée. Nous pouvons le faire facilement en les dérivant - via la valeur de retour des fonctions anonymes. Cela complètera un modèle modulaire de base, et ce qui suit sera un exemple complet:
La copie de code est la suivante:
var module = (function () {
var my = {},
privateVariable = 1;
fonction privateMethod () {
// ...
}
My.ModUleProperty = 1;
my.moduleMethod = function () {
// ...
};
retourner mon;
} ());
Notez que nous avons déclaré un module global appelé module, qui a 2 propriétés publiques: une méthode appelée module.moduleMethod et une variable appelée module.moduleproperty. De plus, il maintient un état intégré privé qui utilise des fermetures de fonctions anonymes. Dans le même temps, nous pouvons facilement importer les variables globales requises et utiliser ce modèle modulaire comme nous l'avons appris auparavant.
Mode avancé
La base décrite dans la section ci-dessus est suffisante pour traiter de nombreuses situations, et maintenant nous pouvons développer ce modèle modulaire pour créer des structures plus puissantes et évolutives. Commençons par le module du module et introduisons ces modes avancés un par un.
Mode zoom
L'ensemble du module doit être une limitation du mode modulaire dans un fichier. Quiconque est impliqué dans un grand projet comprendra la valeur de la division de plusieurs fichiers avec JS. Heureusement, nous avons une grande implémentation pour amplifier les modules. Tout d'abord, nous importons un module, y ajoutons des propriétés et nous l'exportons enfin. Voici un exemple - Zoom avant du module d'origine:
La copie de code est la suivante:
var module = (fonction (my) {
my.anotherMethod = function () {
// Méthode ajoutée ...
};
retourner mon;
}(MODULE));
Nous utilisons le mot clé VAR pour assurer la cohérence, bien qu'il ne soit pas nécessaire ici. Une fois ce code exécuté, notre module a déjà une nouvelle méthode publique appelée module.anotherMethod. Ce fichier amplifié conservera également son propre état intégré privé et des objets importés.
Mode zoom large
Notre exemple ci-dessus nécessite l'exécution de notre module d'initialisation, puis de l'exécution du module amplifié, et bien sûr, cela ne peut pas nécessairement être nécessaire. L'une des meilleures choses que les applications JavaScript peuvent faire pour améliorer les performances est d'exécuter des scripts de manière asynchrone. Nous pouvons créer des modules en multipartes flexibles et leur permettre d'être chargés dans n'importe quel ordre via un mode zoom large. Chaque fichier doit être organisé dans la structure suivante:
La copie de code est la suivante:
var module = (fonction (my) {
// Ajouter des capacités ...
retourner mon;
} (Module || {}));
Dans ce modèle, l'expression VAR le rend nécessaire. Notez que si le module n'a pas été initialisé, cette instruction d'importation créera un module. Cela signifie que vous pouvez utiliser un outil comme LabJS pour charger tous vos fichiers de module en parallèle sans être bloqué.
Mode d'élargissement serré
Le mode élargie est très bon, mais il mettra également certaines limites à votre module. Plus important encore, vous ne pouvez pas écraser en toute sécurité les propriétés d'un module. Vous ne pouvez pas utiliser les propriétés à partir d'autres fichiers lors de l'initialisation (mais vous pouvez les utiliser lors de l'exécution). Le mode d'élargissement serré contient une séquence chargée et permet des propriétés de remplacement. Voici un exemple simple (zoomer dans notre module d'origine):
La copie de code est la suivante:
var module = (fonction (my) {
var old_moduleMethod = my.moduleMethod;
my.moduleMethod = function () {
// Méthode Override, a accès à Old via Old_ModuleMethod ...
};
retourner mon;
}(MODULE));
Nous remplacons l'implémentation de module.ModuleMethod dans l'exemple ci-dessus, mais en cas de besoin, nous pouvons maintenir une référence à la méthode d'origine.
Clone et héritage
La copie de code est la suivante:
var module_two = (fonction (old) {
var my = {},
clé;
pour (clé dans old) {
if (old.hasownproperty (key)) {
ma [clé] = vieille [clé];
}
}
var super_moduleMethod = old.moduleMethod;
my.moduleMethod = function () {
// Méthode remplacée sur le clone, accès à super via super_modulemethod
};
retourner mon;
}(MODULE));
Ce modèle est probablement l'option la plus inflexible. Cela rend le code soigné, mais cela se fait au prix de la flexibilité. Comme je l'ai écrit ci-dessus, si une propriété est un objet ou une fonction, elle ne sera pas copiée, mais deviendra la deuxième référence à l'objet ou à la fonction. Si vous en modifiez l'un, vous modifierez l'autre en même temps (note du traducteur: car ils en sont simplement un!). Cela peut être résolu par un processus de clonage récursif, mais le clonage de la fonction peut ne pas être résolu, peut-être qu'il peut être résolu avec EVAL. Par conséquent, je dis que cette méthode dans cet article ne prend en compte que l'intégrité de l'article.
Variables privées transformatives
Il existe une limitation significative pour diviser un module en plusieurs fichiers: chaque fichier maintient ses propres variables privées et ne peut pas accéder à des variables privées pour d'autres fichiers. Mais ce problème peut être résolu. Voici un exemple d'un module large élargie qui maintient des variables privées à travers les fichiers:
La copie de code est la suivante:
var module = (fonction (my) {
var _private = my._private = my._private || {},
_Seal = my._seal = my._seal || fonction () {
Supprimer mon._Private;
supprimer mon._Seal;
supprimer mon._unSeal;
},
_unSeal = my._unSeal = my._unSeal || fonction () {
my._private = _private;
my._seal = _Seal;
my._unSeal = _unSeal;
};
// Accès permanent à _private, _seal et _unSeal
retourner mon;
} (Module || {}));
Tous les fichiers peuvent définir des propriétés sur leurs variables _private respectives, et il comprend qu'ils sont accessibles par d'autres fichiers. Une fois ce module chargé, l'application peut appeler module._seal () pour empêcher les appels externes vers _private interne. Si ce module doit être remagnifié, la méthode interne dans n'importe quel fichier peut appeler _unSeal () avant de charger le nouveau fichier et appeler à nouveau _Seal () après l'exécution du nouveau fichier. J'utilise ce modèle au travail maintenant et je ne l'ai vu nulle part ailleurs. Je pense que c'est un modèle très utile et cela vaut la peine d'écrire un article sur ce modèle lui-même.
Sous-modules
Notre dernier mode avancé est évidemment le plus facile. Il existe de nombreux excellents exemples de création de sous-modules. C'est comme créer un module normal:
La copie de code est la suivante:
Module.sub = (function () {
var my = {};
// ...
retourner mon;
} ());
Bien que cela semble simple, je pense qu'il convient de mentionner ici. Les sous-modules ont tous les avantages avancés des modules généraux, y compris le mode d'amplification et l'état de privatisation.
en conclusion
La plupart des modes avancés peuvent être combinés pour créer un mode plus utile. Si je veux vraiment recommander un modèle modulaire pour concevoir des applications complexes, je choisirais de combiner le mode d'amplification large, les variables privées et les sous-modules.
Je n'ai pas envisagé les performances de ces modes, mais je préfère transformer cela en une façon de penser plus simple: si un mode modulaire a de bonnes performances, il peut faire un excellent travail pour le minimiser, ce qui facilite le téléchargement de ce fichier de script. L'utilisation du mode d'élargissement large permet des téléchargements parallèles simples non bloquants, ce qui accélère les téléchargements. Le temps d'initialisation peut être légèrement plus lent que les autres méthodes, mais cela en vaut la peine après avoir pesé les avantages et les inconvénients. Tant que l'importation de variable globale est exacte, les performances d'exécution doivent être affectées et il est également possible d'atteindre des vitesses d'exécution plus rapides en sous-modules en raccourcissant la chaîne de référence avec des variables privées.
En conclusion, voici un exemple de module enfant se charge dynamiquement dans son module parent (la créant si le module parent n'existe pas). Pour plus de simplicité, j'ai supprimé les variables privées, et bien sûr, il est très simple d'ajouter des variables privées. Ce modèle de programmation permet de charger une base de code de structure hiérarchique complexe en parallèle à travers des sous-modules.
La copie de code est la suivante:
var util = (fonction (parent, $) {
var my = parent.ajax = parent.ajax || {};
my.get = fonction (url, params, rappel) {
// OK, donc je triche un peu :)
return $ .getjson (URL, params, rappel);
};
// etc...
retour parent;
} (Util || {}, jQuery));
Cet article résume les meilleures pratiques actuelles de la «programmation modulaire JavaScript» et explique comment la mettre en pratique. Bien que ce ne soit pas un tutoriel principal, vous pouvez le comprendre en une petite compréhension de la syntaxe de base de JavaScript.