Le style que vous choisissez pour votre projet devrait être le critère le plus élevé. Placez-le comme une description dans votre projet et liez-le à ce document comme une garantie de cohérence, de lisibilité et de maintenabilité du style de code.
1. Vierge
1. Ne mélangez jamais des espaces et des onglets.
2. Démarrez un projet, sélectionnez Soft Indent (espace) ou TAB (comme méthode d'indentation) avant d'écrire le code et de l'utiliser comme critère le plus élevé.
un). Pour la lisibilité, je recommande toujours de concevoir une indentation de largeur de lettres de 2 lettres dans vos modifications - cela équivaut à deux espaces ou deux espaces au lieu d'un onglet.
3. Si votre éditeur le prend en charge, activez toujours le paramètre "Show Invisible Characters". Les avantages sont:
un). Assurer la cohérence
b). Retirez les espaces à la fin de la ligne
c). Retirer les espaces vides
d). La soumission et la comparaison sont plus lisibles
2. Embellir la grammaire
A. accolades, accolades, pauses de ligne
La copie de code est la suivante:
// si / else / for / while / essai a généralement des accolades, des accolades bouclées et plusieurs lignes
// cela aide à lisible
// 2.a.1.1
// Exemple de syntaxe difficile
if (condition) dosomething ();
tandis que (condition) itérer ++;
pour (var i = 0; i <100; i ++) someIterativefn ();
// 2.a.1.1
// utilise des espaces pour améliorer la lisibilité
if (condition) {
// Déclaration
}
while (condition) {
// Déclaration
}
pour (var i = 0; i <100; i ++) {
// Déclaration
}
// meilleure pratique:
var i,
longueur = 100;
pour (i = 0; i <du long; i ++) {
// Déclaration
}
// ou...
var i = 0,
longueur = 100;
pour (; i <length; i ++) {
// Déclaration
}
var prop;
pour (prop dans objet) {
// Déclaration
}
if (true) {
// Déclaration
} autre {
// Déclaration
}
B. Assign, déclaration, fonction (fonctions nommées, expressions de fonction, fonctions du constructeur)
La copie de code est la suivante:
// 2.b.1.1
// variable
var foo = "bar",
num = 1,
undef;
// Identification littérale:
var array = [],
object = {};
// 2.b.1.2
// Utiliser un seul «var» dans une portée (fonction) aide à améliorer la lisibilité
// et rendez votre liste de déclaration ordonnée (vous sauve également quelques typons de clavier)
// pas bon
var foo = "";
var bar = "";
var qux;
// bien
var foo = "",
bar = "",
quux;
// ou..
var // Commentaires sur ces variables
foo = "",
bar = "",
quux;
// 2.b.1.3
// L'instruction «var» doit toujours être en haut de chaque portée (fonction)
// Convient également aux constantes d'Ecmascript 6
// pas bon
fonction foo () {
// il y a une instruction avant la variable
var bar = "",
qux;
}
// bien
fonction foo () {
var bar = "",
qux;
// Toutes les déclarations sont après la variable
}
// 2.b.2.1
// Déclaration de fonction nommée
fonction foo (arg1, argn) {
}
// Comment utiliser
Foo (Arg1, Argn);
// 2.b.2.2
// Déclaration de fonction nommée
fonction carrée (nombre) {
Numéro de retour * numéro;
}
// Comment utiliser
carré (10);
// Style de passage de continuation très peu naturel
fonction carré (numéro, rappel) {
rappel (numéro * numéro);
}
carré (10, fonction (carré) {
// Contenu de rappel
});
// 2.b.2.3
// Fonction Expression
var carré = fonction (nombre) {
// Renvoie un contenu précieux et pertinent
Numéro de retour * numéro;
};
// Fonction Expression avec identifiant
// Ce formulaire préféré a des fonctions supplémentaires qui lui permettent de s'appeler
// et il y a un identifiant dans la pile
var factorial = fonction factorial (nombre) {
if (nombre <2) {
retour 1;
}
Numéro de retour * factoriel (numéro-1);
};
// 2.b.2.4
// Déclaration de constructeur
fonction foobar (options) {
this.options = options;
}
// Comment utiliser
var foobar = new foobar ({a: "alpha"});
foobar.options;
// {a: "alpha"}
C. Exception, détails
La copie de code est la suivante:
// 2.C.1.1
// fonctionne avec des rappels
foo (function () {
// Remarque: il n'y a pas d'espaces dans les supports et «fonction» du premier appel de fonction
});
// La fonction accepte le «array» comme argument, sans espaces
foo (["alpha", "bêta"]);
// 2.C.1.2
// La fonction accepte «objet» comme argument, sans espaces
foo ({
A: "Alpha",
B: "Beta"
});
// La fonction accepte le littéral «String» comme argument, sans espaces
foo ("bar");
// Il n'y a pas d'espaces à l'intérieur des supports utilisés pour le regroupement
if (! ("foo" dans obj)) {
}
D. La cohérence gagne toujours
Dans les sections 2.A-2.C, l'espace vierge est proposé comme méthode de recommandation, basée sur un objectif simple et supérieur: l'unification. Il convient de noter que les préférences de formatage, telles que «l'espace vierge interne» doivent être facultatifs, mais il ne doit y avoir qu'un seul type de code source de l'ensemble du projet.
La copie de code est la suivante:
// 2.d.1.1
if (condition) {
// Déclaration
}
while (condition) {
// Déclaration
}
pour (var i = 0; i <100; i ++) {
// Déclaration
}
if (true) {
// Déclaration
} autre {
// Déclaration
}
E. guillemets
Peu importe que vous choisissiez des devis simples ou doubles, ils ne font pas de différence d'analyse en JavaScript. Ce qui doit absolument être mandaté, c'est la cohérence. Ne mélangez jamais deux citations dans le même projet, choisissez-en une et gardez-la cohérente.
F. Fin de ligne et ligne vide
Laisser vider la différence et les modifications d'utilisation sont illisibles. Pensez à inclure un crochet pré-engagé qui supprime automatiquement les espaces à la fin de la ligne et des lignes vierges.
3. Détection de type (des directives de style JQuery Core)
A. Type direct (type réel, type réel)
Chaîne:
La copie de code est la suivante:
typeof variable === "String"
Nombre:
La copie de code est la suivante:
typeof variable === "numéro"
Booléen:
La copie de code est la suivante:
typeof variable === "booléen"
Objet:
La copie de code est la suivante:
typeof variable === "objet"
Tableau:
La copie de code est la suivante:
Array.isArray (ArrayLILLIGHOBject)
(Si possible)
Nœud:
La copie de code est la suivante:
elem.nodetype === 1
nul:
La copie de code est la suivante:
variable === null
nul ou indéfini:
La copie de code est la suivante:
variable == null
indéfini:
Variables globales:
La copie de code est la suivante:
typeof variable === "Undefined"
Variables locales:
La copie de code est la suivante:
variable === Undefined
propriété:
La copie de code est la suivante:
object.prop === Undefined
object.hasownproperty (prop)
"Prop" dans l'objet
B. Type de converti (type contraint, types contraints)
Considérez la signification de ce qui suit ...
Étant donné HTML:
La copie de code est la suivante:
<input type = "text" id = "foo-input" value = "1">
// 3.B.1.1
// `foo` a reçu une valeur de` 0`, type `numéro`
var foo = 0;
// type de foo;
// "nombre"
...
// Dans le code ultérieur, vous devez mettre à jour «FOO» et attribuer une nouvelle valeur obtenue dans l'élément d'entrée
foo = document.getElementById ("foo-inter"). valeur;
// Si vous testez `type de foo` maintenant, le résultat sera` String`
// Cela signifie que vous avez une logique similaire à celle-ci lors de la détection de «foo» dans l'instruction if:
if (foo === 1) {
IMPORTANTTASK ();
}
// `IMPORTANTTASK ()` ne sera jamais exécuté, même si `foo 'a une valeur de" 1 "
// 3.B.1.2
// Vous pouvez habilement utiliser l'opérateur +/- unary pour lancer le type pour résoudre le problème:
foo = + document.getElementById ("foo-inter"). valeur;
// ^ + L'opérateur unary convertit l'objet d'opération à sa droite en «nombre»
// type de foo;
// "nombre"
if (foo === 1) {
IMPORTANTTASK ();
}
// `IMPORTANTTASK () 'sera appelé
Voici quelques exemples de casting:
La copie de code est la suivante:
// 3.B.2.1
Numéro var = 1,
String = "1",
bool = false;
nombre;
// 1
numéro + "";
// "1"
chaîne;
// "1"
+ chaîne;
// 1
+ String ++;
// 1
chaîne;
// 2
bool;
// FAUX
+ bool;
// 0
bool + "";
// "FAUX"
// 3.B.2.2
Numéro var = 1,
String = "1",
bool = true;
String === numéro;
// FAUX
String === Numéro + "";
// vrai
+ string === numéro;
// vrai
Bool === Numéro;
// FAUX
+ bool === numéro;
// vrai
Bool === String;
// FAUX
bool === !! String;
// vrai
// 3.b.2.3
var array = ["a", "b", "c"];
!! ~ array.indexof ("a");
// vrai
!! ~ array.indexof ("b");
// vrai
!! ~ array.indexof ("c");
// vrai
!! ~ array.indexof ("d");
// FAUX
// Il convient de noter que ce qui précède est tous "intelligents inutiles"
// utilise un schéma clair pour comparer les valeurs renvoyées
// par exemple Indexof:
if (array.indexof ("a")> = 0) {
// ...
}
// 3.b.2.3
var num = 2,5;
ParseInt (num, 10);
// équivalent à ...
~~ num;
num >> 0;
num >>> 0;
// Les résultats sont tous 2
// Gardez toujours à l'esprit que les valeurs négatives seront traitées différemment ...
var neg = -2,5;
Parseint (Neg, 10);
// équivalent à ...
~~ neg;
nég >> 0;
// Les résultats sont tous -2
// mais...
nég >>> 0;
// Le résultat est 4294967294
4. Opérations comparatives
La copie de code est la suivante:
// 4.1.1
// lorsqu'il juge simplement si un tableau a une longueur, par rapport à l'utilisation de ceci:
if (array.length> 0) ...
// ... Pour déterminer l'authenticité, veuillez utiliser ceci:
if (array.length) ...
// 4.1.2
// lorsqu'il juge simplement si un tableau est vide, par rapport à l'utilisation de ceci:
if (array.length === 0) ...
// ... Pour déterminer l'authenticité, veuillez utiliser ceci:
if (! array.length) ...
// 4.1.3
// en jugeant simplement si une chaîne est vide, relative à l'utilisation de ceci:
if (String! == "") ...
// ... Pour déterminer l'authenticité, veuillez utiliser ceci:
if (String) ...
// 4.1.4
// en jugeant simplement qu'une chaîne est vide, relative à l'utilisation de ceci:
if (String === "") ...
// ... Pour déterminer l'authenticité, veuillez utiliser ceci:
if (! String) ...
// 4.1.5
// en jugeant simplement qu'une référence est vraie, par rapport à l'utilisation de ceci:
if (foo === true) ...
// ... Jugez comme vous le pensez, profitez des avantages des fonctionnalités intégrées:
si (foo) ...
// 4.1.6
// en jugeant simplement qu'une référence est fausse, par rapport à l'utilisation de ceci:
if (foo === false) ...
// ... le convertir en vrai en utilisant la marque d'exclamation
si (! foo) ...
// ... il convient de noter que cela correspondra à 0, "", null, indéfini, nan
// Si vous _Must_ est un type booléen faux, veuillez utiliser ceci:
if (foo === false) ...
// 4.1.7
// Si vous souhaitez calculer une référence, elle peut être nul ou indéfinie, mais ce n'est pas faux, "" ou 0,
// par rapport à l'utilisation de ceci:
if (foo === null || foo === Undefined) ...
// ... Profitez des avantages de la casting de type ==, comme ceci:
if (foo == null) ...
// N'oubliez pas que l'utilisation de == fera du «null» correspondant à «null» et `Undefined»
// mais pas `Faux '," "ou 0
NULL == Undefined
Jugez toujours les valeurs les meilleures et les plus précises, ce qui précède est un guide plutôt qu'un dogme.
La copie de code est la suivante:
// 4.2.1
// Instructions pour les opérations de conversion et de comparaison de type
// Première fois `=== ',` ==' suivi (sauf si une comparaison de type lâche est nécessaire)
// `===` ne fait pas toujours la conversion de type, ce qui signifie:
"1" === 1;
// FAUX
// `==` convertit le type, ce qui signifie:
"1" == 1;
// vrai
// 4.2.2
// boolean, vrai et faux
// Boolean:
Vrai, faux
// réel:
"Foo", 1
// pseudo:
"", 0, null, indéfini, nan, vide 0
5. Style pratique
La copie de code est la suivante:
// 5.1.1
// un module pratique
(fonction (global) {
var module = (function () {
var data = "secret";
retour {
// c'est une valeur booléenne
bool: vrai,
// une chaîne
String: "une chaîne",
// un tableau
tableau: [1, 2, 3, 4],
// un objet
objet: {
Lang: "en-us"
},
getData: function () {
// obtient la valeur de `données»
retourner les données;
},
setData: fonction (valeur) {
// Renvoie la valeur attribuée de `data`
return (data = valeur);
}
};
}) ();
// Certains autres apparaîtront ici
// transforme votre module en un objet global
global.module = module;
})( ce );
// 5.2.1
// une fonction de construction pratique
(fonction (global) {
fonction ctor (foo) {
this.foo = foo;
retourner ceci;
}
Ctor.prototype.getfoo = function () {
Renvoyez ceci.foo;
};
Ctor.prototype.setfoo = fonction (val) {
return (this.foo = val);
};
// N'utilisez pas «new» pour appeler la fonction de construction, vous pourriez le faire:
var ctor = fonction (foo) {
retourner le nouveau ctor (foo);
};
// transforme notre fonction de construction en un objet global
global.ctor = ctor;
})( ce );
6. Nommer
A. Vous n'êtes pas un compilateur / compresseur humain, alors essayez de vous transformer en un seul.
Le code suivant est un exemple de très mauvaise dénomination:
La copie de code est la suivante:
// 6.A.1.1
// Bad Noming Exemple Code
fonction q (s) {
return document.QuerySelectorall (s);
}
var i, a = [], els = q ("# foo");
pour (i = 0; i <els.length; i ++) {a.push (els [i]);}
Il ne fait aucun doute que vous avez écrit un tel code - j'espère qu'il n'apparaîtra plus à partir d'aujourd'hui.
Voici un code avec la même logique, mais avec une dénomination plus robuste et appropriée (et une structure lisible):
La copie de code est la suivante:
// 6.A.2.1
// Amélioration du code d'exemple nommé
requête de fonction (sélecteur) {
return document.QuerySelectorAll (sélecteur);
}
var idx = 0,
éléments = [],
matches = query ("# foo"),
length = matches.length;
pour (; idx <longueur; idx ++) {
elements.push (correspond [idx]);
}
Quelques conseils de dénomination supplémentaires:
La copie de code est la suivante:
// 6.A.3.1
// nommé chaîne
«Dog» est une chaîne
// 6.A.3.2
// Nom des tableaux
`[« chiens »]` est un tableau contenant la corde de chien
// 6.A.3.3
// Nom Fonctions, objets, instances, etc.
camlcase; fonctions et déclarations VAR
// 6.A.3.4
// Nommez le constructeur, le prototype, etc.
Pascalcase; fonction de construction
// 6.A.3.5
// Nommez des expressions régulières
rdesc = //;
// 6.A.3.6
// du guide de style de la bibliothèque de fermeture de Google
functionNameslikethis;
variablenameslikethis;
ConstructornameSlikethis;
EnumnameSlikethis;
MethodNameslikethis;
Symbolic_constants_like_this;
B. Face à ceci
En plus d'utiliser un appel bien connu et une application, .bind (this) ou un fonctionnement fonctionnel est toujours préféré. Créez une déclaration BoundFunction pour les appels ultérieurs, en utilisant un alias lorsqu'il n'y a pas de meilleure option.
La copie de code est la suivante:
// 6.b.1
périphérique de fonction (opts) {
this.value = null;
// Créer un nouveau flux asynchrone, cela sera constamment appelé
Stream.read (opts.path, fonction (data) {
// Utilisez Stream pour renvoyer la dernière valeur des données et mettre à jour la valeur de l'instance
this.value = data;
} .bind (this));
// contrôle la fréquence du déclenchement des événements
setInterval (function () {
// Publier un événement contrôlé
this.emit ("événement");
} .bind (this), opts.freq || 100);
}
// Supposons que nous ayons hérité de l'événement de l'événement;)
Lorsqu'il ne peut pas être exécuté, l'équivalent de .bind est disponible dans la plupart des bibliothèques JavaScript modernes.
La copie de code est la suivante:
// 6.b.2
// Exemple: lodash / sous-traitant, _.bind ()
périphérique de fonction (opts) {
this.value = null;
stream.read (opts.path, _.bind (fonction (data) {
this.value = data;
}, ce) );
setInterval (_. bind (function () {
this.emit ("événement");
}, this), opts.freq || 100);
}
// Exemple: jQuery.proxy
périphérique de fonction (opts) {
this.value = null;
stream.read (opts.path, jQuery.proxy (fonction (data) {
this.value = data;
}, ce) );
setInterval (jQuery.Proxy (function () {
this.emit ("événement");
}, this), opts.freq || 100);
}
// Exemple: dojo.hitch
périphérique de fonction (opts) {
this.value = null;
Stream.Read (opts.path, dojo.hitch (this, function (data) {
this.value = data;
}));
setInterval (dojo.hitch (this, function () {
this.emit ("événement");
}), opts.freq || 100);
}
Fournissez un candidat pour créer un alias pour cela, avec soi comme l'identifiant. Il est très susceptible d'avoir des bogues et devrait être évité autant que possible.
La copie de code est la suivante:
// 6.b.3
périphérique de fonction (opts) {
var self = this;
this.value = null;
Stream.read (opts.path, fonction (data) {
self.value = data;
});
setInterval (function () {
self.emit ("événement");
}, opts.freq || 100);
}
C. Utilisez Thisarg
Plusieurs méthodes prototypes dans ES 5.1 ont une balise ThisArg spéciale intégrée, utilisez-la autant que possible
La copie de code est la suivante:
// 6.c.1
var obj;
obj = {f: "foo", b: "bar", q: "qux"};
Object.keys (obj) .ForEach (function (key) {
// | ceci | C'est maintenant `` OBJ`
console.log (cette [clé]);
}, obj); // <- le dernier paramètre est `thisarg`
// Imprimez ...
// "foo"
// "bar"
// "Qux"
Thisarg peut être utilisé dans array.prototype.every, array.prototype.Forach, array.prototype.some, array.prototype.map et array.prototype.filter.
7. Misc
Les idées et les idées que cette partie expliqueront ne sont pas dogmatiques. Au lieu de cela, il est plus encouragé à être curieux de connaître les pratiques existantes pour essayer de fournir une meilleure solution pour effectuer des tâches de programmation JavaScript générale.
A. Évitez d'utiliser l'interrupteur. Le traçage de la méthode moderne sera les fonctions de liste noire avec des expressions de commutation.
Il semble que Firefox et Chrome aient apporté des améliorations significatives aux instructions de commutation. http://jsperf.com/switch-vs-object-literal-vs-module
Il convient de noter que l'amélioration peut être vue ici: https://github.com/rwldrn/idiomatic.js/issues/13
La copie de code est la suivante:
// 7.A.1.1
// Exemple de déclaration de commutation
switch (foo) {
cas "alpha":
alpha();
casser;
cas "bêta":
bêta();
casser;
défaut:
// Branche par défaut
casser;
}
// 7.A.1.2
// Une méthode qui peut prendre en charge la combinaison et la réutilisation est d'utiliser un objet pour stocker "Cas".
// Utilisez une fonction pour faire la délégation:
Cas VAR, délégant;
// La valeur de retour est pour l'explication uniquement
cas = {
alpha: fonction () {
// Déclaration
// une valeur de retour
return ["alpha", arguments.length];
},
bêta: function () {
// Déclaration
// une valeur de retour
return ["bêta", arguments.length];
},
_default: function () {
// Déclaration
// une valeur de retour
return ["par défaut", arguments.length];
}
};
delegator = function () {
var args, key, délégué;
// convertir `argument 'en un tableau
args = [] .slice.call (arguments);
// Extraire la dernière valeur de «argument»
key = args.shift ();
// appelle la branche par défaut
Delegate = Case._Default;
// déléguer la méthode de l'objet
if (cas.hasownproperty (key)) {
delegate = cas [clé];
}
// La portée de l'ARG peut être définie sur une valeur spécifique,
// Dans ce cas, | null | c'est bien
return Delegate.Apply (null, args);
};
// 7.A.1.3
// Utilisez l'API en 7.A.1.2:
Délégateur ("alpha", 1, 2, 3, 4, 5);
// ["alpha", 5]
// Bien sûr, la valeur de la clé «Case» peut être facilement modifiée à n'importe quelle valeur
var casekey, SomeUserriNput;
// Y a-t-il une entrée possible d'un formulaire?
SomeUserInput = 9;
if (someUserriNput> 10) {
CaseKey = "Alpha";
} autre {
CaseKey = "Beta";
}
// ou...
CaseKey = SomeUserInput> 10? "Alpha": "Beta";
// Alors...
Délégateur (CaseKey, SomeUserriNput);
// ["bêta", 1]
// Bien sûr, cela peut être fait ...
Delegator ();
// ["par défaut", 0]
B. Retourner les valeurs à l'avance pour améliorer la lisibilité du code sans trop de différence de performance
La copie de code est la suivante:
// 7.b.1.1
// pas bon:
fonction returnlate (foo) {
var ret;
if (foo) {
ret = "foo";
} autre {
ret = "quux";
}
retour retour;
}
// bien:
fonction returnarly (foo) {
if (foo) {
retourner "foo";
}
retourner "quux";
}
8. Objets natifs et hôtes (Remarque: J'ai toujours pensé que les objets hôtes ne devraient pas être traduits, donc je le traduiserai selon la méthode d'écriture générale)
Le principe le plus élémentaire est:
Ne faites rien de stupide, les choses iront toujours mieux.
Pour renforcer ce concept, veuillez regarder cette démonstration:
"Tout est autorisé: extension native" par Andrew Dupont (JSConf2011, Portland, Oregon)
http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permited-extending-built-ins-5211542
9. Commentaires
Les commentaires à ligne unique sont placés au-dessus du code comme premier choix
Plusieurs lignes sont ok
Les commentaires à la fin de la ligne doivent être évités!
La méthode JSDOC est également bonne, mais cela prend plus de temps
10. Utilisez une seule langue seule
Quelle que soit la langue que le responsable du programme (ou l'équipe) stipule que le programme est utilisé, le programme ne doit être écrit que dans la même langue.
appendice
Comma d'abord
Tous les projets qui utilisent ce document comme guide de style de base ne permettent pas les formats de code pré-commun, sauf si l'auteur est explicitement spécifié ou requis par l'auteur.