Maison >interface Web >js tutoriel >Style de programmation de développement JavaScript moderne Guide Idiomatic.js Version chinoise_javascript Compétences
Le style que vous choisissez pour votre projet doit répondre aux normes les plus élevées. Placez-le comme description dans votre projet et créez un lien vers ce document comme garantie de cohérence, de lisibilité et de maintenabilité du style de code.
1. Vierge
1. Ne mélangez jamais les espaces et les tabulations.
2. Démarrez un projet et avant d'écrire du code, choisissez l'indentation douce (espaces) ou la tabulation (comme méthode d'indentation) et utilisez-la comme ligne directrice la plus élevée.
a). Pour plus de lisibilité, je recommande toujours de concevoir des retraits de 2 lettres de largeur dans vos éditeurs — cela équivaut à deux espaces ou deux espaces au lieu d'une tabulation.
3. Si votre éditeur le prend en charge, veuillez toujours activer le paramètre « Afficher les caractères invisibles ». Les avantages sont :
a) Assurer la cohérence
b) Supprimer les espaces en fin de ligne
c) Supprimer les espaces sur les lignes vides
d). >
2. Embellir la grammaire
A. Parenthèses, accolades, sauts de ligne// Exemples de syntaxe merdique
while(condition) itération ;
for(var i=0;i<100;i ) someIterativeFn();
//2.A.1.1
// Utiliser des espaces pour améliorer la lisibilité
// Déclaration
}
// Déclaration
}
// Déclaration
}
var i,
longueur = 100;
// déclaration
}
var i = 0,
longueur = 100;
// déclaration
}
pour ( prop dans l'objet ) {
// Déclaration
}
// Déclaration
} else {
// Déclaration
}
var array = [],
object = {};
// Utiliser un seul `var` dans une portée (fonction) permet d'améliorer la lisibilité
// et de garder votre liste de déclarations organisée (vous permet également d'économiser quelques frappes au clavier)
var foo = "";
var bar = "";
var qux;
var foo = "",
bar = "",
quux;
var // Commentaires sur ces variables
foo = "",
bar = "",
quux;
// Les instructions `var` doivent toujours être en haut de leurs portées respectives (fonctions)
// Fonctionne également avec les constantes d'ECMAScript 6
fonction foo() {
var bar = "",
qux;
}
function foo() {
var bar = "",
qux;
}
// 2.B.2.1
// Déclaration de fonction nommée
function foo( arg1, argN ) {
// Utilisation
foo( arg1, argN );
// Déclaration de fonction nommée
function square( number) {
return number * number;
}
carré( 10 );
// Style de passage de continuation très peu naturel
callback( number * number );
}
square( 10, function( square ) {
});
// 2.B.2.3
var square = function( number) {
// Renvoie un contenu précieux et pertinent
return number * number;
} ;
// Expression de fonction avec identifiant
// et a l'identifiant sur la pile
var factorial = function factorial ( number ) {
if ( number < 2 ) {
return 1;
}
renvoie le numéro * factorial( number-1 );
// 2.B.2.4
fonction FooBar( options ) {
this.options = options;
// Utilisation
fooBar.options;
// La fonction accepte `array` comme paramètre, sans espaces
foo([ "alpha", "beta" ]);
// 2.C.1.2
// La fonction accepte `object` comme paramètre, sans espaces
foo({
a: "alpha",
b: "beta"
});
// La fonction accepte le littéral `string` comme paramètre, sans espaces
foo("bar");
//Il n'y a aucun espace à l'intérieur des parenthèses utilisé pour le regroupement
if ( !("foo" in obj) ) {
}
Dans les sections 2.A-2.C, l'espace blanc est proposé comme approche recommandée basée sur un objectif simple et supérieur : l'unité. Il convient de noter que les préférences de formatage telles que « espace blanc interne » doivent être facultatives, mais qu'un seul type doit exister dans le code source de l'ensemble du projet.
if (condition) {
// Déclaration
}
pendant que (condition) {
// Déclaration
}
pour (var i = 0; i < 100; i ) {
// Déclaration
}
if (true) {
// Déclaration
} else {
// Déclaration
}
Peu importe que vous choisissiez des guillemets simples ou des guillemets doubles, ils ne font aucune différence dans l'analyse en JavaScript. Ce qu’il faut absolument faire respecter, c’est la cohérence. Ne mélangez jamais deux types de devis dans un même projet, choisissez-en un et soyez cohérent.
F. Fin de ligne et ligne vierge
Laisser un espace blanc détruira la distinction et rendra l'utilisation des modifications illisible. Pensez à inclure un hook de pré-validation pour supprimer automatiquement les espaces à la fin des lignes et dans les lignes vides.
3. Détection de type (à partir des directives de style jQuery Core)
A. Types directs (types réels, types réels)
Chaîne :
Variables globales :
Considérez la signification de ceci...
Donné HTML :
//3.B.1.1
// `foo` a reçu la valeur `0` et le type est `number`
var foo = 0;
// typeof foo;
// "numéro"
...
// Dans le code suivant, vous devez mettre à jour `foo` pour donner la nouvelle valeur obtenue dans l'élément d'entrée
foo = document.getElementById("foo-input").value;
// Si vous testez maintenant `typeof foo`, le résultat sera `string`
// Cela signifie que votre instruction if pour détecter `foo` a une logique similaire à celle-ci :
if ( foo === 1 ) {
importantTask();
}
// `importantTask()` ne sera jamais exécuté même si `foo` a une valeur "1"
//3.B.1.2
// Vous pouvez intelligemment utiliser l'opérateur unaire / - pour convertir le type afin de résoudre le problème :
foo = document.getElementById("foo-input").value;
// ^ L'opérateur unaire convertit l'opérande de son côté droit en `number`
// typeof foo;
// "numéro"
if ( foo === 1 ) {
importantTask();
}
// `importantTask()` sera appelé
var number = 1,
string = "1",
bool = false;
numéro ;
// 1
numéro "";
// "1"
chaîne;
// "1"
chaîne ;
// 1
chaîne ;
// 1
chaîne;
// 2
bool;
// faux
booléen;
// 0
bool "";
// "faux"
// 3.B.2.2
var number = 1,
string = "1",
bool = true;
string === nombre;
// false
string === nombre "";
// vrai
string === nombre;
// vrai
bool === nombre;
// faux
bool === nombre;
// vrai
bool === string;
// false
bool === !!string;
// true
// 3.B.2.3
var array = [ "a", "b", "c" ];
!!~array.indexOf("a");
//true
!!~array.indexOf("b");
//true
!!~array.indexOf("c");
//true
!!~array.indexOf("d");
// false
// Il convient de noter que les éléments ci-dessus sont "inutilement intelligents"
// Utilisez une solution claire pour comparer les valeurs renvoyées
// Comme indexOf :
if ( array.indexOf( "a" ) >= 0 ) {
// ...
}
// 3.B.2.3
var num = 2,5;
parseInt( num, 10 );
// Equivalent à...
~~num;
numéro>> 0;
numéro>>> 0;
//Le résultat est toujours 2
// Gardez toujours à l'esprit que les valeurs négatives seront traitées différemment...
var nég = -2,5;
parseInt( neg, 10 );
// Equivalent à...
~~nég;
nég>> 0;
// Le résultat est toujours -2
// Mais...
nég>>> 0;
//Le résultat est 4294967294
4.Opération de comparaison
// ...Pour déterminer l'authenticité, veuillez utiliser ceci :
if (array.length) ...
// 4.1.2
// Pour juger simplement si un tableau est vide, utilisez plutôt ceci :
if (array.length === 0) ...
// ...Pour déterminer l'authenticité, veuillez utiliser ceci :
if ( !array.length ) ...
// 4.1.3
// Lorsque vous jugez simplement si une chaîne est vide, utilisez plutôt ceci :
if ( string !== "" ) ...
// ...Pour déterminer l'authenticité, veuillez utiliser ceci :
if (string) ...
// 4.1.4
// Pour juger simplement si une chaîne est vide, utilisez plutôt ceci :
if ( string === "" ) ...
// ...Pour déterminer l'authenticité, veuillez utiliser ceci :
if ( !string ) ...
// 4.1.5
// Lorsque vous jugez simplement si une référence est vraie, utilisez plutôt ceci :
if ( foo === true ) ...
// ... jugez comme vous pensez et profitez des avantages des fonctions intégrées :
if ( foo ) ...
// 4.1.6
// Lorsque vous jugez simplement si une référence est fausse, utilisez plutôt ceci :
if ( foo === false ) ...
// ...convertissez-le en vrai en utilisant un point d'exclamation
if ( !foo ) ...
// ...Il est à noter que : ceci correspondra à 0, "", null, undefined, NaN
// Si vous _devez_ être faux de type booléen, veuillez l'utiliser comme ceci :
si ( foo === false ) ...
// 4.1.7
// Si vous souhaitez calculer une référence, elle peut être nulle ou indéfinie, mais elle n'est pas fausse, "" ou 0,
// Au lieu d'utiliser ceci :
if ( foo === null || foo === non défini ) ...
// ...profitez des avantages du casting de type ==, comme ceci :
if ( foo == null ) ...
// N'oubliez pas que l'utilisation de == fera correspondre `null` à `null` et `undefined`
// mais pas `false`, "" ou 0
null == undefined
Jugez toujours de la valeur la meilleure et la plus précise, ce qui précède est une ligne directrice et non un dogme.
// `===` en premier, `==` en second (sauf si une comparaison vaguement typée est requise)
// `===` n'effectue jamais de conversion de type, ce qui signifie :
"1" === 1;
// faux
// `==` convertira le type, ce qui signifie :
"1" == 1;
// vrai
// 4.2.2
// Booléen, Vrai & Faux
// Booléen :
vrai, faux
// Vrai :
"foo", 1
// Pseudo :
"", 0, nul, indéfini, NaN, vide 0
5. Style pratique
(function( global) {
var Module = (function() {
var data = "secret";
return {
// Ceci est une valeur booléenne
bool: true,
bool: true,
// Une chaîne
chaîne: "une chaîne",
/ / Un tableau
array : [ 1, 2, 3, 4 ],
// Un objet
object : {
lang : "en-Us"
},
getData : function() {
data = valeur );
. }
};
})();
// Quelques autres apparaîtront ici
// Transformez votre module en objet global
})( ceci );
// 5.2.1
(fonction( global ) {
fonction Ctor( foo ) {
this.foo = foo;
renvoie ceci ;
}Ctor.prototype.getFoo = function() {
return this.foo;
};
Ctor.prototype.setFoo = function( val ) {
return ( this.foo = val );
};
// Au lieu d'utiliser `new` pour appeler le constructeur, vous pouvez faire ceci :
var ctor = function( foo ) {
return new Ctor( foo );
// Transforme notre constructeur en objet global
global.ctor = ctor;
6. Nommer
A. Vous n'êtes pas un compilateur/compresseur humain, alors essayez de le devenir.
Le code suivant est un exemple de dénomination extrêmement mauvaise :
function q(s) {
return document.querySelectorAll(s);
}
var i,a=[],els=q("#foo");
for( i=0;i
Vous avez sans aucun doute écrit un tel code - j'espère qu'il n'apparaîtra plus jamais à partir d'aujourd'hui.
Voici un code pour la même logique, mais avec une dénomination plus robuste et appropriée (et une structure lisible) :
function query( selector ) {
return document.querySelectorAll( selector );
}
var idx = 0,
elements = [],
matches = query("#foo"),
length = matches.length;
for ( ; idx < length; idx ) {
elements.push( matches[ idx ] );
}
`dog` est une chaîne
// 6.A.3.2
// Tableaux nommés
`['dogs']` est un tableau
contenant la `dog string// 6.A.3.3
// Fonctions, objets, instances nommés, etc.
camlCase ; fonction et déclaration var
// 6.A.3.4
// Constructeurs nommés, prototypes, etc.
PascalCase; fonction constructeur
// 6.A.3.5
// Expressions régulières nommées
rDesc = //;
// 6.A.3.6
// Tiré du guide de style de la bibliothèque de fermeture de Google
functionNamesLikeThis;
variableNamesLikeThis;
ConstructorNamesLikeThis;
EnumNamesLikeThis;
methodNamesLikeThis;
SYMBOLIC_CONSTANTS_LIKE_THIS;
En plus d'utiliser le célèbre call and apply, préférez toujours .bind( this ) ou un équivalent fonctionnel de celui-ci. Créez une déclaration BoundFunction pour les appels ultérieurs, en utilisant des alias uniquement lorsqu'il n'y a pas de meilleure alternative.
this.value = null;
// Créer un nouveau flux asynchrone, qui sera appelé en continu
stream.read( opts.path, function( 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ôler la fréquence de déclenchement des événements
setInterval(function() {
// Émettre un événement contrôlé
this.emit("event");
}.bind(this), opts.freq || 100 );
}
// Supposons que nous ayons hérité de l'émetteur d'événements (EventEmitter) ;)
Lorsque cela ne fonctionne pas, une fonctionnalité équivalente à .bind est disponible dans la plupart des bibliothèques JavaScript modernes.
// Exemple : lodash/underscore, _.bind()
function Device( opts ) {
this.value = null;
stream.read( opts.path, _.bind(function( data ) {
this.value = data;
}, ceci) );
setInterval(_.bind(function() {
this.emit("événement");
}, ceci), opts.freq || 100 );
}
// Exemple : jQuery.proxy
function Device( opts ) {
this.value = null;
stream.read( opts.path, jQuery.proxy(function( data ) {
this.value = data;
}, ceci) );
setInterval( jQuery.proxy(function() {
this.emit("événement");
}, ceci), opts.freq || 100 );
}
// Exemple : dojo.hitch
function Device( 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 );
}
function Device( opts ) {
var self = this;
this.value = null;
stream.read( opts.path, function( data ) {
self.value = data;
});
setInterval(function() {
self.emit("event");
}, opts.freq || 100 );
}
C. Utilisez cetArg
Plusieurs méthodes de prototype dans ES 5.1 ont une balise thisArg spéciale intégrée, utilisez-la autant que possible
var obj;
obj = { f : "foo", b : "bar", q : "qux" };
Object.keys( obj ).forEach(function( key ) {
// |ceci| est maintenant `obj`
console.log( this[ clé ] );
}, obj ); // <-- Le dernier paramètre est `thisArg`
//Imprimez-le...
// "foo"
// "bar"
// "qux"
7. Divers
Les idées et concepts qui seront expliqués dans cette section ne sont pas des dogmes. Au lieu de cela, cela encourage la curiosité à l'égard des pratiques existantes pour tenter de fournir de meilleures solutions pour les tâches générales de programmation JavaScript.
A. Évitez d'utiliser switch, le traçage des méthodes modernes mettra sur liste noire les fonctions avec des expressions switch.
Il semble que les instructions switch aient été considérablement améliorées dans les dernières versions de Firefox et de Chrome. http://jsperf.com/switch-vs-object-literal-vs-module
Il est à noter que les améliorations peuvent être vues ici : https://github.com/rwldrn/idiomatic.js/issues/13
switch( foo ) {
case "alpha":
alpha();
break;
case "beta":
beta();
break;
default :
//Branche par défaut
break;
}
// 7.A.1.2
// Une façon de prendre en charge la composition et la réutilisation est d'utiliser un objet pour stocker des "cas",
// Utiliser une fonction pour déléguer :
cas var, délégant;
// La valeur de retour est à titre d'illustration uniquement
cases = {
alpha: function() {
// Instruction
// Une valeur de retour
return [ "Alpha", arguments .length ];
},
bêta : function() {
// Déclaration
// Une valeur de retour
return [ "Beta", arguments.length ];
} ,
_default: function() {
// Instruction
// Une valeur de retour
return [ "Default", arguments.length ];
}
};
délégué = fonction() {
var args, clé, délégué ;
// Convertir `argument` en tableau
args = [].slice.call( arguments );
// Extraire la première valeur de `argument`
key = args.shift();
// Appeler la branche par défaut
délégué = cases._default;
// Déléguer les méthodes de l'objet
if ( cases.hasOwnProperty( key ) ) {
délégué = cases[ key ];
}
// La portée de arg peut être définie sur une valeur spécifique,
// Dans ce cas, |null| convient
return délégué.apply( null, args );
};
// 7.A.1.3
// Utilisation de l'API en 7.A.1.2 :
délégué( "alpha", 1, 2, 3, 4, 5 );
// [ "Alpha", 5 ]
// Bien sûr, la valeur de la clé `case` peut être facilement modifiée en n'importe quelle valeur
var caseKey, someUserInput;
// Est-il possible qu'il s'agisse d'une forme de saisie ?
someUserInput = 9;
if ( someUserInput > 10 ) {
caseKey = "alpha";
} else {
caseKey = "beta";
}
// Ou...
caseKey = someUserInput > 10 ? "alpha" : "bêta";
// Alors...
délégué( caseKey, someUserInput );
// [ "Beta", 1 ]
// Bien sûr que vous pouvez le faire de cette façon...
délégué();
// [ "Par défaut", 0 ]
B. Renvoyer la valeur plus tôt améliore la lisibilité du code sans grande différence de performances
if ( foo ) {
ret = "foo";
} else {
ret = "quux";
}
return ret;
>
// D'accord :
fonction returnEarly( foo ) {
if ( foo ) {
return "foo";
}
return "quux";
}
8. Objets natifs et hôtes (Remarque : en fait, j'ai toujours pensé que les objets hôtes ne devaient pas être traduits, je vais donc les traduire selon la façon dont ils sont écrits dans les livres ordinaires)
Le principe le plus fondamental est :
Ne faites rien de stupide, les choses iront mieux.
Pour renforcer cette idée, regardez cette démo :
« Tout est permis : extensions natives » par Andrew Dupont (JSConf2011, Portland, Oregon)
http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permit-extending-built-ins-5211542
9. Remarques
Les commentaires sur une seule ligne placés au-dessus du code sont préférés
Plusieurs lignes sont également possibles
Les commentaires de fin de ligne doivent être évités !
La méthode JSDoc est également bonne, mais elle prend plus de temps
10. Utiliser une seule langue
Les programmes ne doivent être écrits que dans la même langue, quelle que soit la langue spécifiée par le responsable du programme (ou l'équipe).
Annexe
La virgule d'abord
Tous les projets qui utilisent ce document comme guide de style de base n'autorisent pas le formatage du code avec des virgules de début, sauf indication contraire ou demande explicite de l'auteur.