Maison > interface Web > js tutoriel > Style de programmation de développement JavaScript moderne Guide Idiomatic.js Version chinoise_javascript Compétences

Style de programmation de développement JavaScript moderne Guide Idiomatic.js Version chinoise_javascript Compétences

WBOY
Libérer: 2016-05-16 16:46:34
original
1465 Les gens l'ont consulté

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


Copier le code Le code est le suivant :
// if/else/for/while/try ont généralement des parenthèses, des accolades et plusieurs lignes
// Cela facilite la lisibilité
// 2.A.1.1

// Exemples de syntaxe merdique

if(condition) doSomething();

while(condition) itération ;

for(var i=0;i<100;i ) someIterativeFn();

//2.A.1.1

// Utiliser 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 approche :

var i,

longueur = 100;

pour ( i = 0; i < length; i ) {

// déclaration
}

// Ou...

var i = 0,

longueur = 100;

for ( ; i < length; i ) {

// déclaration
}

var prop ;

pour ( prop dans l'objet ) {

// Déclaration
}

if ( true ) {

// Déclaration
} else {
// Déclaration
}

B. Affectation, déclaration, fonction (fonction nommée, expression de fonction, fonction constructeur)

Copier le code Le code est le suivant :
// 2.B. 1.1
// Variable
var foo = "bar",
num = 1,
undef;

//Identificateur littéral :

var array = [],
object = {};

// 2.B.1.2

// 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)

// Mauvais

var foo = "";
var bar = "";
var qux;

// OK

var foo = "",
bar = "",
quux;

// Or..

var // Commentaires sur ces variables
foo = "",
bar = "",
quux;

// 2.B.1.3

// Les instructions `var` doivent toujours être en haut de leurs portées respectives (fonctions)
// Fonctionne également avec les constantes d'ECMAScript 6

// Mauvaise

fonction foo() {

// Il y a une instruction avant la variable

var bar = "",

qux;
}

// OK

function foo() {
var bar = "",
qux;

// Toutes les instructions sont après les variables

}
// 2.B.2.1
// Déclaration de fonction nommée
function foo( arg1, argN ) {

}

// Utilisation

foo( arg1, argN );

// 2.B.2.2

// Déclaration de fonction nommée
function square( number) {
return number * number;
}

// Comment utiliser

carré( 10 );
// Style de passage de continuation très peu naturel

function square( number, callback) {

callback( number * number );
}

square( 10, function( square ) {

// contenu de rappel

});

// 2.B.2.3

// Expression de fonction

var square = function( number) {
// Renvoie un contenu précieux et pertinent
return number * number;
} ;

// Expression de fonction avec identifiant

// Cette forme préférée a une fonctionnalité supplémentaire qui lui permet de s'appeler

// 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

// Déclaration du constructeur

fonction FooBar( options ) {

this.options = options;

}


// Utilisation

var fooBar = new FooBar({ a: "alpha" });


fooBar.options;

// { a : "alpha" }


C. Exceptions, détails


Copier le code Le code est le suivant :

// 2.C.1.1
// Fonction avec rappel
foo(function() {
// Remarque : les parenthèses et `function` dans le premier appel de fonction Il y a pas d'espaces
});

// 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) ) {

}


D. La cohérence gagne toujours

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.

Copier le code Le code est le suivant :

// 2.D.1.1

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
}


Citations

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 :

Copier le code Le code est le suivant :

typeof variable == = "string"

Numéro :
Copier le code Le code est le suivant :

typeof variable = == "number"

Booléen :
Copier le code Le code est le suivant :

typeof variable === "booléen"

Objet :
Copier le code Le code est le suivant :

typeof variable === "object"

Array :
Copier le code Le code est le suivant :

Array.isArray( arrayLikeObject )
(si possible)

Noeud :
Copier le code Le code est le suivant :

elem.nodeType === 1

null :
Copier le code Le code est le suivant :

variable === null

Nul ou non défini :
Copier le code Le code est le suivant :

variable = = nul

non défini :

Variables globales :

Copier le codeLe code est le suivant :

type de variable = == " non défini"

Variable locale :
Copier le code Le code est le suivant :

variable === non défini

Attribut :
Copier le code Le code est le suivant :

object.prop === non défini
object.hasOwnProperty( prop )
"prop" dans l'objet

Type de conversion (type forcé, types contraints)

Considérez la signification de ceci...

Donné HTML :

Copier le code Le code est le suivant :

//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é


Pour les castings, voici quelques exemples :
Copier le code Le code est le suivant :

// 3.B.2.1

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

Copier le code Le code est le suivant :

// 4.1.1
// Lorsque vous jugez simplement si un tableau a une longueur, utilisez plutôt ceci :
if ( array.length > 0 ) ...

// ...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.

Copier le code Le code est le suivant :

// 4.2.1
/ / Instructions d'opération de conversion et de comparaison de type

// `===` 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

Copier le code Le code est le suivant :

// 5.1.1
// Un module 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

global.Module = Module;

})( ceci );


// 5.2.1

// Une fonction de construction pratique

(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;

})( ceci );

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 :

Copiez le code Le code est le suivant :

// 6.A.1.1
// Exemple de code mal nommé

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) :

Copier le code Le code est le suivant :

// 6.A.2.1
// Exemple de code de dénomination amélioré

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 ] );
}


Quelques conseils de dénomination supplémentaires :
Copier le code Le code est le suivant :

// 6.A.3.1
// Chaîne nommée

`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;


Faire face à ça

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.

Copier le code Le code est le suivant :

// 6.B.1
fonction Appareil (opts) {

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.

Copier le code Le code est le suivant :

// 6.B.2

// 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 );
}


Fournissez un candidat pour créer un alias de celui-ci avec soi comme identifiant. Ceci est très bogué et doit être évité si possible.
Copier le code Le code est le suivant :

// 6.B.3

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

Copier le code Le le code est le suivant :

// 6.C.1

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"


thisArg est dans Array.prototype.every, Array.prototype.forEach, Array. prototype Il peut être utilisé dans .some, Array.prototype.map et Array.prototype.filter.

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

Copier le code Le code est le suivant :

// 7.A.1.1
// Exemple d'instruction Switch

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

Copier le code Le code est tel suit :

// 7.B.1.1
// Mauvais :
function returnLate( foo ) {
var ret;

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.

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal