Question Meilleures pratiques généralement acceptées en matière d'organisation de code en JavaScript [fermé]


Comme les frameworks JavaScript comme jQuery rendent les applications web côté client plus riches et plus fonctionnelles, j'ai commencé à remarquer un problème ...

Comment dans le monde gardez-vous cela organisé?

  • Mettez tous vos gestionnaires en un seul endroit et écrivez des fonctions pour tous les événements?
  • Créer une fonction / classes pour envelopper toutes vos fonctionnalités?
  • Ecrire comme un fou et espérer que ça marche pour le mieux?
  • Abandonner et obtenir une nouvelle carrière?

Je mentionne jQuery, mais c'est vraiment n'importe quel code JavaScript en général. Je constate que lorsque les lignes sur les lignes commencent à s'accumuler, il devient plus difficile de gérer les fichiers de script ou de trouver ce que vous cherchez. Très probablement, les plus gros problèmes que j'ai trouvés sont qu'il y a tellement de façons de faire la même chose, il est difficile de savoir laquelle est la meilleure pratique actuellement acceptée.

Existe-t-il des recommandations générales sur la meilleure façon de garder votre .js des fichiers aussi beaux et soignés que le reste de votre application? Ou est-ce juste une question d'IDE? Y at-il une meilleure option là-bas?


MODIFIER

Cette question était destinée à être plus sur l'organisation du code et non sur l'organisation des fichiers. Il y a eu de très bons exemples de fusion de fichiers ou de partage de contenu.

Ma question est la suivante: quelle est la meilleure façon d'organiser votre code? Quelle est votre façon, ou même une façon recommandée d'interagir avec les éléments de la page et de créer du code réutilisable qui ne sont pas en conflit les uns avec les autres?

Certaines personnes ont énuméré espaces de noms ce qui est une bonne idée. Quelles sont d'autres façons, plus spécifiquement de traiter les éléments sur la page et de garder le code organisé et soigné?


537
2017-10-29 15:19


origine


Réponses:


Ce serait beaucoup plus agréable si javascript avait des espaces de noms, mais je trouve que l'organisation de choses comme Dustin Diaz décrit ici m'aide beaucoup.

var DED = (function() {

    var private_var;

    function private_method()
    {
        // do stuff here
    }

    return {
        method_1 : function()
            {
                // do stuff here
            },
        method_2 : function()
            {
                // do stuff here
            }
    };
})();

J'ai mis différents "namespaces" et parfois des classes individuelles dans des fichiers séparés. Habituellement, je commence avec un fichier et comme une classe ou un espace de noms devient assez grand pour le justifier, je le sépare dans son propre fichier. Utiliser un outil pour combiner tous vos fichiers pour la production est également une excellente idée.


170



J'essaie d'éviter d'inclure du javascript avec le HTML. Tout le code est encapsulé dans des classes et chaque classe est dans son propre fichier. Pour le développement, j'ai des balises <script> séparées pour inclure chaque fichier js, mais elles sont fusionnées en un seul paquet plus grand pour la production afin de réduire la surcharge des requêtes HTTP.

Généralement, je vais avoir un seul fichier js 'principal' pour chaque application. Donc, si j'écrivais une application "survey", j'aurais un fichier js appelé "survey.js". Cela contiendrait le point d'entrée dans le code jQuery. Je crée des références jQuery pendant l'instanciation, puis les passe dans mes objets en tant que paramètres. Cela signifie que les classes javascript sont 'pures' et ne contiennent aucune référence aux identifiants CSS ou aux noms de classes.

// file: survey.js
$(document).ready(function() {
  var jS = $('#surveycontainer');
  var jB = $('#dimscreencontainer');
  var d = new DimScreen({container: jB});
  var s = new Survey({container: jS, DimScreen: d});
  s.show();
});

Je trouve également que la convention de dénomination est importante pour la lisibilité. Par exemple: je ajoute "j" à toutes les instances de jQuery.

Dans l'exemple ci-dessus, il existe une classe appelée DimScreen. (Supposons que cela assombrit l'écran et ouvre une boîte d'alerte.) Il a besoin d'un élément div qu'il peut agrandir pour couvrir l'écran, puis ajouter une boîte d'alerte, donc je passe dans un objet jQuery. jQuery a un concept de plug-in, mais il a semblé limitatif (par exemple, les instances ne sont pas persistantes et inaccessibles) sans réel avantage. La classe DimScreen est donc une classe javascript standard qui utilise justement jQuery.

// file: dimscreen.js
function DimScreen(opts) { 
   this.jB = opts.container;
   // ...
}; // need the semi-colon for minimizing!


DimScreen.prototype.draw = function(msg) {
  var me = this;
  me.jB.addClass('fullscreen').append('<div>'+msg+'</div>');
  //...
};

J'ai construit des appliations assez complexes en utilisant cette approche.


83



Vous pouvez diviser vos scripts en fichiers séparés pour le développement, puis créer une version "release" où vous les cassez tous ensemble et exécutez Compresseur YUI ou quelque chose de similaire à ce sujet.


37



Inspiré par les messages précédents, j'ai fait une copie de Rakefile et vendeur répertoires distribués avec WysiHat (un RTE mentionné par changelog) et fait quelques modifications pour inclure le contrôle de code avec JSLint et minification avec Compresseur YUI.

L'idée est d'utiliser Pignons (à partir de WysiHat) pour fusionner plusieurs JavaScripts en un seul fichier, vérifier la syntaxe du fichier fusionné avec JSLint et le réduire avec YUI Compressor avant la distribution.

Conditions préalables

  • Java Runtime
  • rubis et rake gem
  • Vous devriez savoir comment mettre un JAR dans Classpath

Maintenant faites

  1. Télécharger Rhinocéros et placez le JAR ("js.jar") sur votre chemin de classe
  2. Télécharger Compresseur YUI et placez le JAR (build / yuicompressor-xyz.jar) dans votre chemin de classe
  3. Télécharger WysiHat et copiez le répertoire "fournisseur" à la racine de votre projet JavaScript
  4. Télécharger JSLint pour Rhino et placez-le dans le répertoire "fournisseur"

Créez maintenant un fichier nommé "Rakefile" dans le répertoire racine du projet JavaScript et ajoutez le contenu suivant:

require 'rake'

ROOT            = File.expand_path(File.dirname(__FILE__))
OUTPUT_MERGED   = "final.js"
OUTPUT_MINIFIED = "final.min.js"

task :default => :check

desc "Merges the JavaScript sources."
task :merge do
  require File.join(ROOT, "vendor", "sprockets")

  environment  = Sprockets::Environment.new(".")
  preprocessor = Sprockets::Preprocessor.new(environment)

  %w(main.js).each do |filename|
    pathname = environment.find(filename)
    preprocessor.require(pathname.source_file)
  end

  output = preprocessor.output_file
  File.open(File.join(ROOT, OUTPUT_MERGED), 'w') { |f| f.write(output) }
end

desc "Check the JavaScript source with JSLint."
task :check => [:merge] do
  jslint_path = File.join(ROOT, "vendor", "jslint.js")

  sh 'java', 'org.mozilla.javascript.tools.shell.Main',
    jslint_path, OUTPUT_MERGED
end

desc "Minifies the JavaScript source."
task :minify => [:merge] do
  sh 'java', 'com.yahoo.platform.yui.compressor.Bootstrap', '-v',
    OUTPUT_MERGED, '-o', OUTPUT_MINIFIED
end

Si vous avez tout fait correctement, vous devriez pouvoir utiliser les commandes suivantes dans votre console:

  • rake merge - fusionner différents fichiers JavaScript en un seul
  • rake check - vérifier la syntaxe de votre code (ceci est le défaut tâche, de sorte que vous pouvez simplement taper rake)
  • rake minify - pour préparer la version minifiée de votre code JS

Sur la fusion de sources

En utilisant Sprockets, le préprocesseur JavaScript que vous pouvez inclure (ou require) autres fichiers JavaScript. Utilisez la syntaxe suivante pour inclure d'autres scripts du fichier initial (nommé "main.js", mais vous pouvez le modifier dans le fichier Rake):

(function() {
//= require "subdir/jsfile.js"
//= require "anotherfile.js"

    // some code that depends on included files
    // note that all included files can be in the same private scope
})();

Et alors...

Jetez un oeil à Rakefile fourni avec WysiHat pour mettre en place le test de l'unité automatisée. Jolies choses :)

Et maintenant pour la réponse

Cela ne répond pas très bien à la question initiale. Je sais et je suis désolé à ce sujet, mais je l'ai posté ici parce que j'espère qu'il sera peut-être utile à quelqu'un d'autre d'organiser son mess.

Mon approche du problème consiste à faire autant de modélisation orientée objet que possible et à séparer les implémentations en différents fichiers. Ensuite, les gestionnaires doivent être aussi courts que possible. L'exemple avec ListSingleton est aussi sympa.

Et les espaces de noms ... et bien ils peuvent être imités par une structure d'objet plus profonde.

if (typeof org === 'undefined') {
    var org = {};
}

if (!org.hasOwnProperty('example')) {
    org.example = {};
}

org.example.AnotherObject = function () {
    // constructor body
};

Je ne suis pas un grand fan des imitations, mais cela peut être utile si vous avez de nombreux objets que vous souhaitez sortir de la portée globale.


26



L'organisation du code nécessite l'adoption de conventions et de normes de documentation:
1. Code d'espace de nom pour un fichier physique;

Exc = {};


2. Classer des groupes dans ces espaces de noms javascript;
3. Définir des prototypes ou des fonctions ou classes associées pour représenter des objets du monde réel;


Exc = {};
Exc.ui = {};
Exc.ui.maskedInput = function (mask) {
    this.mask = mask;
    ...
};
Exc.ui.domTips = function (dom, tips) {
    this.dom = gift;
    this.tips = tips;
    ...
};


4. Définissez des conventions pour améliorer le code. Par exemple, regroupez toutes ses fonctions ou méthodes internes dans son attribut de classe d'un type d'objet.

Exc.ui.domTips = function (dom, tips) {
    this.dom = gift;
    this.tips = tips;
    this.internal = {
        widthEstimates: function (tips) {
            ...
        }
        formatTips: function () {
            ...
        }
    };
    ...
};


5. Faites la documentation des espaces de noms, des classes, des méthodes et des variables. En cas de besoin, discutez également de certaines parties du code (certaines IF et Fors implémentent généralement une logique importante du code).

/**
  * Namespace <i> Example </i> created to group other namespaces of the "Example".  
  */
Exc = {};
/**
  * Namespace <i> ui </i> created with the aim of grouping namespaces user interface.
  */
Exc.ui = {};

/**
  * Class <i> maskdInput </i> used to add an input HTML formatting capabilities and validation of data and information.
  * @ Param {String} mask - mask validation of input data.
  */
Exc.ui.maskedInput = function (mask) {
    this.mask = mask;
    ...
};

/**
  * Class <i> domTips </i> used to add an HTML element the ability to present tips and information about its function or rule input etc..
  * @ Param {String} id - id of the HTML element.
  * @ Param {String} tips - tips on the element that will appear when the mouse is over the element whose identifier is id <i> </i>.
  */
  Exc.ui.domTips = function (id, tips) {
    this.domID = id;
    this.tips = tips;
    ...
};


Ce ne sont que quelques conseils, mais cela a grandement aidé à organiser le code. Rappelez-vous que vous devez avoir de la discipline pour réussir!


18



Le fait de suivre de bons principes de conception OO et de concevoir des modèles contribue grandement à rendre votre code facile à maintenir et à comprendre. Mais l'une des meilleures choses que j'ai découvert récemment sont les signaux et les slots aka publish / subscribe. Jettes un coup d'oeil à http://markdotmeyer.blogspot.com/2008/09/jquery-publish-subscribe.html pour une implémentation jQuery simple.

L'idée est bien utilisée dans d'autres langages pour le développement de l'interface graphique. Lorsque quelque chose d'important se produit quelque part dans votre code, vous publiez un événement synthétique global auquel d'autres méthodes d'autres objets peuvent s'abonner. Cela donne une excellente séparation des objets.

Je pense que Dojo (et Prototype?) Ont une version intégrée de cette technique.

voir également Quels sont les signaux et les slots?


13



J'ai réussi à appliquer le Modèle de module Javascript à une application Ext JS à mon travail précédent. Il a fourni un moyen simple de créer du code bien encapsulé.


12



Dojo avait le système de modules dès le premier jour. En fait, il est considéré comme une pierre angulaire du dojo, la colle qui le maintient tous ensemble:

Utilisation de modules Dojo atteint les objectifs suivants:

  • Espaces de noms pour le code Dojo et le code personnalisé (dojo.declare()) - ne polluent pas l'espace global, ne coexistent pas avec d'autres bibliothèques, et le code non-Dojo de l'utilisateur.
  • Chargement de modules de manière synchrone ou asynchrone par nom (dojo.require()).
  • Génère des constructions personnalisées en analysant les dépendances des modules pour créer un seul fichier ou un groupe de fichiers interdépendants (appelés couches) afin d'inclure uniquement les besoins de votre application Web. Les versions personnalisées peuvent également inclure des modules Dojo et des modules fournis par le client.
  • Accès CDN transparent à Dojo et code de l'utilisateur. À la fois AOL et Google portent Dojo de cette manière, mais certains clients le font aussi pour leurs applications Web personnalisées.

11



Check-out JavasciptMVC.

Vous pouvez :

  • divisez votre code en couches de modèle, de vue et de contrôleur.

  • compresser tout le code dans un seul fichier de production

  • code généré automatiquement

  • créer et exécuter des tests unitaires

  • et beaucoup plus...

Le meilleur de tous, il utilise jQuery, de sorte que vous pouvez profiter des autres plugins jQuery aussi.


9



Mon patron parle encore de l'époque où ils ont écrit du code modulaire (langage C), et se plaint de la façon dont le code est maintenant moche! On dit que les programmeurs peuvent écrire des assemblages dans n'importe quel cadre. Il y a toujours une stratégie pour surmonter l'organisation du code. Le problème de base est avec les gars qui traitent le script java comme un jouet et n'essaient jamais de l'apprendre.

Dans mon cas, j'écris des fichiers js sur un thème d'interface utilisateur ou un écran d'application, avec un init_screen approprié (). En utilisant la convention de nommage id appropriée, je m'assure qu'il n'y a pas de conflits d'espace de nom au niveau de l'élément racine. Dans le discret window.load (), je lie les choses en fonction de l'identifiant de niveau supérieur.

J'utilise strictement des fermetures et des modèles de script Java pour masquer toutes les méthodes privées. Après cela, jamais confronté à un problème de propriétés / définitions de fonctions / définitions de variables. Cependant, lorsque vous travaillez avec une équipe, il est souvent difficile d'imposer la même rigueur.


9