Guide de style JavaScript
Table des matières
- Types
- Objets
- Tableaux
- Chaînes de caractères
- Fonctions
- Propriétés
- Variables
- Expressions conditionnelles et égalité
- block
- Commentaires
- Espaces blancs
- Virgules
- Points-virgules
- Conversion de type et coercition
- Conventions de nommage
- Accesseurs
- Constructeurs
- Événements
- Modules
- jQuery
- Compatibilité ES5
- Séparation du HTML, du CSS et du JavaScript
- Utilisation de jsHint
- Outils front-end
Types
- Valeurs primitives: Équivalent à un passage par valeur (les objets JavaScript fournissent tous des littéraux), utilisez des littéraux pour créer des objets.
stringnumberbooleannullundefined
var foo = 1,
bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 9
Types complexes: Équivalent à un passage par référence
objectarrayfunction
var foo = [1, 2],
bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
Objets
- Utilisez des valeurs littérales pour créer des objets.
// bad var item = new Object(); // good var item = {}; - N'utilisez pas de mots réservésmots réservéscomme clés.
// bad var superman = { class: 'superhero', default: { clark: 'kent' }, private: true }; // good var superman = { klass: 'superhero', defaults: { clark: 'kent' }, hidden: true };
Tableaux
- Utilisez des valeurs littérales pour créer des tableaux.
// bad var items = new Array(); // good var items = [];
- Si vous ne connaissez pas la longueur du tableau, utilisez push.
var someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra'); - Utilisez slice lorsque vous devez copier un tableau. jsPerf.
var len = items.length, itemsCopy = [], i; // bad for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good itemsCopy = items.slice(); - Utilisez slice pour convertir des objets similaires à des tableaux en tableaux.
function trigger() { var args = [].slice.apply(arguments); ... }
Chaînes de caractères
- Utilisez des guillemets simples pour les chaînes de caractères
''(Parce que la plupart du temps, nos chaînes de caractères, en particulier HTML, contiendront")。// bad var name = "Bob Parr"; // good var name = 'Bob Parr'; // bad var fullName = "Bob " + this.lastName; // good var fullName = 'Bob ' + this.lastName;
- Les chaînes de caractères dépassant 80 caractères (certains spécifient 140, le projet peut définir sa propre limite) doivent utiliser la concaténation de chaînes pour les sauts de ligne.
- Remarque : si elle est utilisée à l'excès, une longue concaténation de chaînes peut affecter les performances.
// bad var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.'; // bad var errorMessage = 'This is a super long error that \ was thrown because of Batman. \ When you stop to think about \ how Batman had anything to do \ with this, you would get nowhere \ fast.'; // good var errorMessage = 'This is a super long error that ' + 'was thrown because of Batman.' + 'When you stop to think about ' + 'how Batman had anything to do ' + 'with this, you would get nowhere ' + 'fast.';
- Lorsque vous programmez, utilisez join au lieu de la concaténation de chaînes pour construire des chaînes.
var items, messages, length, i; messages = [{ state: 'success', message: 'This one worked.' },{ state: 'success', message: 'This one worked as well.' },{ state: 'error', message: 'This one did not work.' }]; length = messages.length; // bad function inbox(messages) { items = '<ul>'; for (i = 0; i < length; i++) { items += '<li>' + messages[i].message + '</li>'; } return items + '</ul>'; } // good function inbox(messages) { items = []; for (i = 0; i < length; i++) { items[i] = messages[i].message; } return '<ul><li>' + items.join('</li><li>') + '</li></ul>'; }
Fonctions
- Expressions de fonction :
// 匿名函数表达式 var anonymous = function() { return true; }; // 有名函数表达式 var named = function named() { return true; }; // 立即调用函数表达式 (function() { console.log('Welcome to the Internet. Please follow me.'); })(); - Ne déclarez jamais une fonction dans un bloc qui n'est pas une fonction ; affectez plutôt cette fonction à une variable. Les navigateurs vous permettent de le faire, mais ils l'interprètent différemment.
- Remarque :ECMA-262 définit
blockcomme un ensemble d'instructions ; une déclaration de fonction n'est pas une instruction. Lisez l'explication d'ECMA-262 sur ce problème.。// bad if (currentUser) { function test() { console.log('Nope.'); } } // good if (currentUser) { var test = function test() { console.log('Yup.'); }; } - Ne jamais nommer un paramètre
arguments, cela écrasera l'argumentsobjet passé dans la portée de la fonction.// bad function nope(name, options, arguments) { // ...stuff... } // good function yup(name, options, args) { // ...stuff... }
Propriétés
- Lorsque vous utilisez des variables et des noms de variables spéciaux non valides, vous pouvez utiliser des crochets pour accéder aux propriétés (
.préféré).var luke = { jedi: true, age: 28 }; function getProp(prop) { return luke[prop]; } var isJedi = getProp('jedi');
Variables
- Utilisez toujours
varpour déclarer des variables. Sinon, des variables globales seront créées, et nous devons éviter de polluer l'espace de noms global.// bad superPower = new SuperPower(); // good var superPower = new SuperPower();
- Utilisez un seul
varet des retours à la ligne pour déclarer plusieurs variables, avec une indentation de 4 espaces.// bad var items = getItems(); var goSportsTeam = true; var dragonball = 'z'; // good var items = getItems(), goSportsTeam = true, dragonball = 'z'; - Déclarez les variables non assignées en dernier, ce qui est utile lorsque vous souhaitez référencer des variables précédemment assignées.
// bad var i, len, dragonball, items = getItems(), goSportsTeam = true; // bad var i, items = getItems(), dragonball, goSportsTeam = true, len; // good var items = getItems(), goSportsTeam = true, dragonball, length, i; - Déclarez les variables en haut de la portée pour éviter les problèmes liés à la déclaration et à l'assignation des variables.
// bad function() { test(); console.log('doing stuff..'); //..other stuff.. var name = getName(); if (name === 'test') { return false; } return name; } // good function() { var name = getName(); test(); console.log('doing stuff..'); //..other stuff.. if (name === 'test') { return false; } return name; } // bad function() { if (!arguments.length) { return false; } var name = getName(); return true; } // good function() { var name = getName(); if (!arguments.length) { return false; } return true; }
Expressions conditionnelles et égalité
- Utilisez de manière appropriée
===et!==et==et!=。 - Utilisez les opérations logiques dans les expressions de manière appropriée.
- La coercition de type dans les expressions conditionnelles suit ces règles :
- Les objetssont évalués commetrue
- Undefinedest évalué commefalse
- Nullest évalué commefalse
- Les booléenssont évalués commeune valeur booléenne
- Les nombresS'il s'agit de+0, -0 ou NaNil est évalué commefalse, sinon commevrai
- Les chaînes de caractèresSi c'est une chaîne vide
''elle est évaluée commefalse, sinon commetrue
if ([0]) { // true // An array is an object, objects evaluate to true }
- Utilisez des raccourcis.
// bad if (name !== '') { // ...stuff... } // good if (name) { // ...stuff... } // bad if (collection.length > 0) { // ...stuff... } // good if (collection.length) { // ...stuff... } - LisezTruth Equality and JavaScriptpour en savoir plus.
block
- Utilisez des accolades pour tous les blocs multilignes.
// bad if (test) return false; // good if (test) return false; // good if (test) { return false; } // bad function() { return false; } // good function() { return false; }
- Utiliser
/** ... */pour les commentaires multilignes, y compris les descriptions, les types spécifiés, les valeurs des paramètres et les valeurs de retour.// bad // make() returns a new element // based on the passed in tag name // // @param <String> tag // @return <Element> element function make(tag) { // ...stuff... return element; } // good /** * make() returns a new element * based on the passed in tag name * * @param <String> tag * @return <Element> element */ function make(tag) { // ...stuff... return element; } - Utiliser
//pour les commentaires sur une seule ligne. Placez le commentaire sur une seule ligne au-dessus de l’objet commenté, et laissez une ligne vide avant le commentaire.// bad var active = true; // is current tab // good // is current tab var active = true; // bad function getType() { console.log('fetching type...'); // set the default type to 'no type' var type = this._type || 'no type'; return type; } // good function getType() { console.log('fetching type...'); // set the default type to 'no type' var type = this._type || 'no type'; return type; } - Si vous avez un problème qui doit être réexaminé, ou si vous proposez une solution qui doit être mise en œuvre, faites précéder votre commentaire de
FIXMEouTODOpour aider les autres à comprendre rapidement.function Calculator() { // FIXME: shouldn't use a global here total = 0; return this; }function Calculator() { // TODO: total should be configurable by an options param this.total = 0; return this; } - Pour une documentation conforme aux spécifications, lorsque de la documentation est nécessaire, vous pouvez essayerjsdoc。
Espaces blancs
- L’indentation et le formatage aident l’équipe à localiser et corriger les bogues du code plus rapidement.
- Réglez les tabulations sur 4 espaces.
// bad function() { ∙∙var name; } // bad function() { ∙var name; } // good function() { ∙∙∙∙var name; } - Mettez un espace avant l’accolade ouvrante.
// bad function test(){ console.log('test'); } // good function test() { console.log('test'); } // bad dog.set('attr',{ age: '1 year', breed: 'Bernese Mountain Dog' }); // good dog.set('attr', { age: '1 year', breed: 'Bernese Mountain Dog' }); - Utilisez l’indentation pour les longues chaînes de méthodes.
// bad $('#items').find('.selected').highlight().end().find('.open').updateCount(); // good $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount(); // bad var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true) .attr('width', (radius + margin) * 2).append('svg:g') .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') .call(tron.led); // good var leds = stage.selectAll('.led') .data(data) .enter().append('svg:svg') .class('led', true) .attr('width', (radius + margin) * 2) .append('svg:g') .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') .call(tron.led);
Virgules
- Ne mettez pas de virgules au début.
// bad var once , upon , aTime; // good var once, upon, aTime; // bad var hero = { firstName: 'Bob' , lastName: 'Parr' , heroName: 'Mr. Incredible' , superPower: 'strength' }; // good var hero = { firstName: 'Bob', lastName: 'Parr', heroName: 'Mr. Incredible', superPower: 'strength' }; - N’ajoutez pas de virgules finales supplémentaires. Cela peut causer des erreurs dans IE, et s’il y a une virgule supplémentaire, certaines implémentations d’ES3 calculeront une longueur de tableau supplémentaire.
// bad var hero = { firstName: 'Kevin', lastName: 'Flynn', }; var heroes = [ 'Batman', 'Superman', ]; // good var hero = { firstName: 'Kevin', lastName: 'Flynn' }; var heroes = [ 'Batman', 'Superman' ];
Points-virgules
- Ajoutez toujours des points-virgules à la fin des instructions.
// bad (function() { var name = 'Skywalker' return name })() // good (function() { var name = 'Skywalker'; return name; })(); // good ;(function() { var name = 'Skywalker'; return name; })();
Conversion de type et coercition
- Effectuez la conversion de type au début de l’instruction.
- Chaînes de caractères :
// => this.reviewScore = 9; // bad var totalScore = this.reviewScore + ''; // good var totalScore = '' + this.reviewScore; // bad var totalScore = '' + this.reviewScore + ' total score'; // good var totalScore = this.reviewScore + ' total score';
- Pour les nombres, utilisez
parseIntet incluez toujours la base pour la conversion de type, par ex.,parseInt(value, 10)。 -
var inputValue = '4'; // bad var val = new Number(inputValue); // bad var val = +inputValue; // bad var val = inputValue >> 0; // bad var val = parseInt(inputValue); // good var val = Number(inputValue); // good var val = parseInt(inputValue, 10); // good /** * parseInt was the reason my code was slow. * Bitshifting the String to coerce it to a * Number made it a lot faster. */ var val = inputValue >> 0;
- Booléens :
var age = 0; // bad var hasAge = new Boolean(age); // good var hasAge = Boolean(age); // good var hasAge = !!age;
Conventions de nommage
- Évitez les noms d’un seul caractère ; faites en sorte que les noms de vos variables soient descriptifs.
// bad function q() { // ...stuff... } // good function query() { // ..stuff.. } - Utilisez camelCase pour nommer les objets, les fonctions et les instances.
// bad var OBJEcttsssss = {}; var this_is_my_object = {}; var this-is-my-object = {}; function c() {}; var u = new user({ name: 'Bob Parr' }); // good var thisIsMyObject = {}; function thisIsMyFunction() {}; var user = new User({ name: 'Bob Parr' }); - Utilisez PascalCase pour nommer les constructeurs ou les classes.
// bad function user(options) { this.name = options.name; } var bad = new user({ name: 'nope' }); // good function User(options) { this.name = options.name; } var good = new User({ name: 'yup' }); - Préfixez les propriétés privées avec un trait de soulignement
_:// bad this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; // good this._firstName = 'Panda';
- Lorsque vous enregistrez une référence à
thisuseself(python 风格), évitezthis issue. Angular recommande d’utiliservm(MVVM模式中view-model):// good function() { var self = this; return function() { console.log(self); }; }
Accesseurs
- Les fonctions d’accès pour les propriétés ne sont pas requises.
- Si vous avez des fonctions d'accès, utilisez getVal() et setVal('hello'),
java getter、setter风格oujQuery风格。 - Si la propriété est un booléen, utilisez isVal() ou hasVal().
// bad if (!dragon.age()) { return false; } // good if (!dragon.hasAge()) { return false; } - Vous pouvez créer des fonctions get() et set(), mais gardez-les cohérentes.
function Jedi(options) { options || (options = {}); var lightsaber = options.lightsaber || 'blue'; this.set('lightsaber', lightsaber); } Jedi.prototype.set = function(key, val) { this[key] = val; }; Jedi.prototype.get = function(key) { return this[key]; };
Constructeurs
- Assignez les méthodes au prototype de l'objet au lieu d'écraser le prototype avec un nouvel objet. Écraser le prototype peut entraîner des problèmes d'héritage.
function Jedi() { console.log('new jedi'); } // bad Jedi.prototype = { fight: function fight() { console.log('fighting'); }, block: function block() { console.log('blocking'); } }; // good Jedi.prototype.fight = function fight() { console.log('fighting'); }; Jedi.prototype.block = function block() { console.log('blocking'); }; - Les méthodes peuvent retourner
thispour aider les méthodes à être chaînables.// bad Jedi.prototype.jump = function() { this.jumping = true; return true; }; Jedi.prototype.setHeight = function(height) { this.height = height; }; var luke = new Jedi(); luke.jump(); // => true luke.setHeight(20) // => undefined // good Jedi.prototype.jump = function() { this.jumping = true; return this; }; Jedi.prototype.setHeight = function(height) { this.height = height; return this; }; var luke = new Jedi(); luke.jump() .setHeight(20); - Vous pouvez écrire une méthode toString() personnalisée, mais assurez-vous qu'elle fonctionne correctement et n'a pas d'effets secondaires.
function Jedi(options) { options || (options = {}); this.name = options.name || 'no name'; } Jedi.prototype.getName = function getName() { return this.name; }; Jedi.prototype.toString = function toString() { return 'Jedi - ' + this.getName(); };
Événements
- Lorsque vous attachez des données à des événements, passez un hash au lieu d'une valeur primitive. Cela permet aux contributeurs ultérieurs d'ajouter davantage de données aux données de l'événement sans avoir à rechercher et à mettre à jour le gestionnaire d'événements pour cet événement.
// bad $(this).trigger('listingUpdated', listing.id); ... $(this).on('listingUpdated', function(e, listingId) { // do something with listingId });Mieux :
// good $(this).trigger('listingUpdated', { listingId : listing.id }); ... $(this).on('listingUpdated', function(e, data) { // do something with data.listingId });
Modules
- Le fichier doit être nommé en camelCase, placé dans un dossier du même nom, et avoir un nom cohérent lors de l'exportation.
- Pour les bibliothèques d'API publiques, envisagez d'ajouter une méthode nommée noConflict() qui définit le module exporté comme la version précédente et le renvoie.
- Déclarez toujours en haut du module
'use strict';, import[JSHint规范](http://jshint.com/):// fancyInput/fancyInput.js (function(global) { 'use strict'; var previousFancyInput = global.FancyInput; function FancyInput(options) { this.options = options || {}; } FancyInput.noConflict = function noConflict() { global.FancyInput = previousFancyInput; return FancyInput; }; global.FancyInput = FancyInput; })(this);
jQuery
- Pour les objets jQuery, commencez par
$au début pour les distinguer des nœuds DOM natifs.// bad var menu = $(".menu"); // good var $menu = $(".menu"); - Mettre en cache les requêtes jQuery
// bad function setSidebar() { $('.sidebar').hide(); // ...stuff... $('.sidebar').css({ 'background-color': 'pink' }); } // good function setSidebar() { var $sidebar = $('.sidebar'); $sidebar.hide(); // ...stuff... $sidebar.css({ 'background-color': 'pink' }); } - Utilisez la mise en cascade pour les requêtes DOM
$('.sidebar ul')ou$('.sidebar ul'),jsPerf. - Pour les requêtes d'objets jQuery à portée limitée, utilisez
find:// bad $('.sidebar', 'ul').hide(); // bad $('.sidebar').find('ul').hide(); // good $('.sidebar ul').hide(); // good $('.sidebar > ul').hide(); // good (slower) $sidebar.find('ul'); // good (faster) $($sidebar[0]).find('ul'); - Utilisez l'événement document ready une seule fois par page, ce qui facilite le débogage et le suivi du flux de comportement.
$(function(){ //do your page init. }); - Utilisez les événements
jQuery.onséparés de la page dans des fichiers JavaScript.// bad <a id="myLink" href="../index.html" onclick="myEventHandler();"></a> // good <a id="myLink" href="../index.html"></a> $("#myLink").on("click", myEventHandler); - Utilisez l'approche promise pour Ajax.
// bad $.ajax({ ... success : function(){ }, error : function(){ } }) // good $.ajax({. .. }).then( function( ){ // success }, function( ){ // error }) - Utilisez les objets différés de promise pour résoudre les problèmes d'enregistrement différé.
var dtd = $.Deferred(); // 新建一个deferred对象 var wait = function(dtd){ var tasks = function(){ alert("执行完毕!"); dtd.resolve(); // 改变deferred对象的执行状态 }; setTimeout(tasks,5000); return dtd; }; - Déplacez les styles en HTML et JavaScript vers des classes CSS ; utilisez des classes en HTML et JavaScript au lieu de styles directs.
Compatibilité ECMAScript 5
Utilisez autant que possible les méthodes ES5, en particulier les méthodes map, filter et forEach des tableaux, pour simplifier le développement quotidien. Dans les anciens navigateurs IE, introduisezES5-shim. Vous pouvez également envisager d'introduireunderscore、lodashbibliothèques d'aide courantes.
- RéférenceKangaxES5table de compatibilité。
Séparation du HTML, du CSS et du JavaScript
- Utilisez HTML pour la structure DOM de la page, CSS pour les styles et JavaScript pour les opérations DOM dynamiques. Ne les mélangez pas dans le HTML.
- Séparez-les en différents types de fichiers et liez les fichiers.
- Les noms de variables HTML, CSS et JavaScript doivent tous avoir une valeur métier. CSS utilise des noms tout en minuscules séparés par des tirets, tandis que JavaScript utilise le camelCase avec la première lettre en minuscule.
- CSS peut introduireBootstrap, Foundation et d'autres frameworks de conception responsive bien connus. Utilisez également les outils SASS et LESS pour écrire du CSS.
- Pour CSS et JavaScript, il est recommandé de les fusionner en un seul fichier afin de réduire le nombre de connexions Ajax. Vous pouvez également introduire la méthode de chargement AMD (Require.js).
- Pour la plupart des systèmes de gestion d'entreprise internes, vous pouvez essayer d'adopter des frameworks front-endMVCpour organiser le code. Tels qu'Angular, l'architecture React + flux, Knockout, etc.
- Pour la compatibilité, vous pouvez utiliserModernizrdes bibliothèques de spécifications pour vous aider.
Utilisation de jsHint
- Il est recommandé d'introduirejshintplugins dans les projets front-end afin de normaliser les normes de codage du projet. Disposer également d'un ensemble complet de configurations IDE.
- Remarque : jshint nécessite l'introduction des outils nodejs grunt ou des plugins gulp. Un serveur privé npm nodejs de niveau entreprise est recommandé.
Outils front-end
- Outil de gestion des paquets JavaScript tiers front-end bower (
bower install jQuery), bower peut mettre en œuvre la résolution des dépendances, le téléchargement, la gestion des mises à niveau, etc. pour les bibliothèques tierces. Il est recommandé de mettre en place un serveur privé bower de niveau entreprise. - Pour les outils de build front-end, les outils grunt ou gulp peuvent être utilisés pour réaliser toutes les tâches front-end telles que la compression html, css, js, la validation, les tests, la fusion de fichiers, watch et liveload. Un serveur privé npm nodejs de niveau entreprise est recommandé.
- IDE de développement front-end : WebStorm (Idea) et Sublime sont les meilleurs. L'équipe projet doit utiliser un IDE unifié. Une configuration IDE unifiée est très importante.
Articles connexes
- Normes de codage JavaScript
- Les normes de code JavaScript les plus populaires
- Guide de style de code JavaScript
Source : http://greengerong.github.io/blog/2015/05/09/qian-duan-javascriptgui-fan