JavaScript-Stilrichtlinie
Inhaltsverzeichnis
- Typen
- Objekte
- Arrays
- Zeichenketten
- Funktionen
- Eigenschaften
- Variablen
- Bedingte Ausdrücke und Gleichheit
- block
- Kommentare
- Leerraum
- Kommas
- Semikolons
- Typumwandlung & Typenzwang
- Namenskonventionen
- Accessoren
- Konstruktoren
- Ereignisse
- Module
- jQuery
- ES5-Kompatibilität
- Trennung von HTML, CSS und JavaScript
- jsHint verwenden
- Front-End-Tools
Typen
- Primitive Werte: Entspricht der Übergabe per Wert (JavaScript-Objekte bieten alle Literale), verwenden Sie Literale, um Objekte zu erstellen.
stringnumberbooleannullundefined
var foo = 1,
bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 9
Komplexe Typen: Entspricht der Übergabe per Referenz
objectarrayfunction
var foo = [1, 2],
bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
Objekte
- Verwenden Sie Literalwerte, um Objekte zu erstellen.
// bad var item = new Object(); // good var item = {}; - Verwenden Sie keine reservierten Wörterreservierte Wörterals Schlüssel.
// bad var superman = { class: 'superhero', default: { clark: 'kent' }, private: true }; // good var superman = { klass: 'superhero', defaults: { clark: 'kent' }, hidden: true };
Arrays
- Verwenden Sie Literalwerte, um Arrays zu erstellen.
// bad var items = new Array(); // good var items = [];
- Wenn du die Array-Länge nicht kennst, verwende push.
var someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra'); - Verwende slice, wenn du ein Array kopieren musst. jsPerf.
var len = items.length, itemsCopy = [], i; // bad for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good itemsCopy = items.slice(); - Verwende slice, um array-ähnliche Objekte in Arrays umzuwandeln.
function trigger() { var args = [].slice.apply(arguments); ... }
Zeichenketten
- Verwende einfache Anführungszeichen für Strings
''(Denn meistens werden unsere Strings, insbesondere HTML, enthalten")。// bad var name = "Bob Parr"; // good var name = 'Bob Parr'; // bad var fullName = "Bob " + this.lastName; // good var fullName = 'Bob ' + this.lastName;
- Strings, die 80 Zeichen überschreiten (manche geben 140 an, das Projekt kann eigene festlegen), sollten für Zeilenumbrüche String-Konkatenation verwenden.
- Hinweis: Bei übermäßigem Gebrauch kann lange String-Konkatenation die Performance beeinträchtigen.
// 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.';
- Verwende beim Programmieren join anstelle von String-Konkatenation, um Strings zu erstellen.
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>'; }
Funktionen
- Funktionsausdrücke:
// 匿名函数表达式 var anonymous = function() { return true; }; // 有名函数表达式 var named = function named() { return true; }; // 立即调用函数表达式 (function() { console.log('Welcome to the Internet. Please follow me.'); })(); - Deklariere niemals eine Funktion in einem Nicht-Funktionsblock; weise diese Funktion stattdessen einer Variablen zu. Browser erlauben dir das, aber sie parsen es unterschiedlich.
- Hinweis:ECMA-262 definiert
blockals eine Reihe von Anweisungen; eine Funktionsdeklaration ist keine Anweisung. Lies die Erklärung von ECMA-262 zu diesem Problem.。// bad if (currentUser) { function test() { console.log('Nope.'); } } // good if (currentUser) { var test = function test() { console.log('Yup.'); }; } - Benenne niemals einen Parameter
arguments, dies überschreibt dasargumentsObjekt, das innerhalb des Funktionsbereichs übergeben wird.// bad function nope(name, options, arguments) { // ...stuff... } // good function yup(name, options, args) { // ...stuff... }
Eigenschaften
- Wenn du Variablen und spezielle ungültige Variablennamen verwendest, kannst du eckige Klammern verwenden, um auf Eigenschaften zuzugreifen (
.bevorzugt).var luke = { jedi: true, age: 28 }; function getProp(prop) { return luke[prop]; } var isJedi = getProp('jedi');
Variablen
- Verwenden Sie immer
varzum Deklarieren von Variablen. Andernfalls werden globale Variablen erstellt, und wir sollten vermeiden, den globalen Namensraum zu verschmutzen.// bad superPower = new SuperPower(); // good var superPower = new SuperPower();
- Verwende eine einzelne
varund Zeilenumbrüche, um mehrere Variablen zu deklarieren, eingerückt mit 4 Leerzeichen.// bad var items = getItems(); var goSportsTeam = true; var dragonball = 'z'; // good var items = getItems(), goSportsTeam = true, dragonball = 'z'; - Deklariere nicht zugewiesene Variablen zuletzt, was nützlich ist, wenn du auf zuvor zugewiesene Variablen verweisen möchtest.
// 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; - Deklariere Variablen am Anfang des Gültigkeitsbereichs, um Probleme im Zusammenhang mit Variablendeklaration und -zuweisung zu vermeiden.
// 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; }
Bedingte Ausdrücke und Gleichheit
- Verwende angemessen
===und!==und==und!=。 - Verwende logische Operationen in Ausdrücken angemessen.
- Typumwandlung in bedingten Ausdrücken folgt diesen Regeln:
- Objektewerden alstrue ausgewertet
- Undefinedwird alsfalse ausgewertet
- Nullwird alsfalse ausgewertet
- Boolean-Wertewerden alsboolescher Wert ausgewertet
- ZahlenWenn es+0, -0 oder NaNist, wird es alsfalseausgewertet, andernfalls alswahr
- StringsWenn es eine leere Zeichenkette ist
''wird es alsfalseausgewertet, andernfalls alstrue
if ([0]) { // true // An array is an object, objects evaluate to true }
- Verwende Kurzformen.
// bad if (name !== '') { // ...stuff... } // good if (name) { // ...stuff... } // bad if (collection.length > 0) { // ...stuff... } // good if (collection.length) { // ...stuff... } - LiesTruth Equality and JavaScript, um mehr zu erfahren.
block
- Verwende geschweifte Klammern für alle mehrzeiligen Blöcke.
// bad if (test) return false; // good if (test) return false; // good if (test) { return false; } // bad function() { return false; } // good function() { return false; }
- Verwenden Sie
/** ... */für mehrzeilige Kommentare, einschließlich Beschreibungen, spezifizierter Typen, Parameterwerte und Rückgabewerte.// 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; } - Verwenden Sie
//für einzeilige Kommentare. Platzieren Sie den einzeiligen Kommentar über dem kommentierten Objekt und fügen Sie eine Leerzeile vor dem Kommentar ein.// 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; } - Wenn Sie ein Problem haben, das erneut überprüft werden muss, oder wenn Sie eine Lösung vorschlagen, die umgesetzt werden muss, stellen Sie Ihrem Kommentar Folgendes voran
FIXMEoderTODOum anderen zu helfen, schnell zu verstehen.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; } - Für spezifikationskonforme Dokumentation können Sie, wenn Dokumentation benötigt wird,jsdoc ausprobieren。
Leerraum
- Einrückung und Formatierung helfen dem Team, Codefehler schneller zu finden und zu beheben.
- Tabs auf 4 Leerzeichen einstellen.
// bad function() { ∙∙var name; } // bad function() { ∙var name; } // good function() { ∙∙∙∙var name; } - Ein Leerzeichen vor die öffnende geschweifte Klammer setzen.
// 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' }); - Bei langen Methodenketten Einrückung verwenden.
// 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);
Kommas
- Keine Kommas am Anfang setzen.
// 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' }; - Keine zusätzlichen nachgestellten Kommas hinzufügen. Dies kann Fehler im IE verursachen, und wenn ein zusätzliches Komma vorhanden ist, berechnen einige ES3-Implementierungen eine zusätzliche Array-Länge.
// bad var hero = { firstName: 'Kevin', lastName: 'Flynn', }; var heroes = [ 'Batman', 'Superman', ]; // good var hero = { firstName: 'Kevin', lastName: 'Flynn' }; var heroes = [ 'Batman', 'Superman' ];
Semikolons
- Semikolons immer am Ende von Anweisungen hinzufügen.
// bad (function() { var name = 'Skywalker' return name })() // good (function() { var name = 'Skywalker'; return name; })(); // good ;(function() { var name = 'Skywalker'; return name; })();
Typumwandlung & Typenzwang
- Typkonvertierung am Anfang der Anweisung durchführen.
- Zeichenketten:
// => 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';
- Verwenden Sie für Zahlen
parseIntund geben Sie immer den radix für die Typkonvertierung an, z. B.,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;
- Boolesche Werte:
var age = 0; // bad var hasAge = new Boolean(age); // good var hasAge = Boolean(age); // good var hasAge = !!age;
Namenskonventionen
- Vermeiden Sie einbuchstabige Namen; lassen Sie Ihre Variablennamen beschreibend sein.
// bad function q() { // ...stuff... } // good function query() { // ..stuff.. } - Verwenden Sie camelCase beim Benennen von Objekten, Funktionen und Instanzen.
// 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' }); - Verwenden Sie PascalCase beim Benennen von Konstruktoren oder Klassen.
// 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' }); - Stellen Sie privaten Eigenschaften einen Unterstrich voran
_:// bad this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; // good this._firstName = 'Panda';
- Wenn Sie eine Referenz auf
thisVerwenden Sieself(python 风格), vermeiden Siethis issue. Angular empfiehlt die Verwendung vonvm(MVVM模式中view-model):// good function() { var self = this; return function() { console.log(self); }; }
Accessoren
- Accessor-Funktionen für Eigenschaften sind nicht erforderlich.
- Wenn Sie Accessor-Funktionen haben, verwenden Sie getVal() und setVal('hello'),
java getter、setter风格oderjQuery风格。 - Wenn die Eigenschaft ein Boolean ist, verwenden Sie isVal() oder hasVal().
// bad if (!dragon.age()) { return false; } // good if (!dragon.hasAge()) { return false; } - Sie können get()- und set()-Funktionen erstellen, aber halten Sie sie konsistent.
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]; };
Konstruktoren
- Weisen Sie Methoden dem Prototyp des Objekts zu, anstatt den Prototyp mit einem neuen Objekt zu überschreiben. Das Überschreiben des Prototyps kann Vererbungsprobleme verursachen.
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'); }; - Methoden können zurückgeben
thisum Methoden verkettbar zu machen.// 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); - Sie können eine benutzerdefinierte toString()-Methode schreiben, aber stellen Sie sicher, dass sie korrekt funktioniert und keine Nebenwirkungen hat.
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(); };
Ereignisse
- Wenn Sie Daten an Ereignisse anhängen, übergeben Sie einen Hash anstelle eines primitiven Werts. Dadurch können spätere Mitwirkende den Ereignisdaten weitere Daten hinzufügen, ohne den Event-Handler für dieses Ereignis suchen und aktualisieren zu müssen.
// bad $(this).trigger('listingUpdated', listing.id); ... $(this).on('listingUpdated', function(e, listingId) { // do something with listingId });Besser:
// good $(this).trigger('listingUpdated', { listingId : listing.id }); ... $(this).on('listingUpdated', function(e, data) { // do something with data.listingId });
Module
- Die Datei sollte in camelCase benannt, in einem Ordner mit demselben Namen abgelegt werden und beim Exportieren einen konsistenten Namen haben.
- Erwägen Sie für öffentliche API-Bibliotheken, eine Methode namens noConflict() hinzuzufügen, die das exportierte Modul auf die vorherige Version setzt und es zurückgibt.
- Immer am Anfang des Moduls deklarieren
'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
- Für jQuery-Objekte beginnen Sie mit
$am Anfang, um sie von nativen DOM-Knoten zu unterscheiden.// bad var menu = $(".menu"); // good var $menu = $(".menu"); - jQuery-Abfragen zwischenspeichern
// 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' }); } - Kaskadierung für DOM-Abfragen verwenden
$('.sidebar ul')oder$('.sidebar ul'), jsPerf. - Für bereichsbezogene jQuery-Objektabfragen verwenden Sie
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'); - Verwenden Sie das document ready-Ereignis nur einmal pro Seite, was das Debuggen und Nachverfolgen des Verhaltensflusses erleichtert.
$(function(){ //do your page init. }); - Ereignisse verwenden
jQuery.onvom Seitencode getrennt in JavaScript-Dateien.// bad <a id="myLink" href="../index.html" onclick="myEventHandler();"></a> // good <a id="myLink" href="../index.html"></a> $("#myLink").on("click", myEventHandler); - Verwenden Sie den Promise-Ansatz für Ajax.
// bad $.ajax({ ... success : function(){ }, error : function(){ } }) // good $.ajax({. .. }).then( function( ){ // success }, function( ){ // error }) - Verwenden Sie die Deferred-Objekte von Promise, um Probleme bei der verzögerten Registrierung zu lösen.
var dtd = $.Deferred(); // 新建一个deferred对象 var wait = function(dtd){ var tasks = function(){ alert("执行完毕!"); dtd.resolve(); // 改变deferred对象的执行状态 }; setTimeout(tasks,5000); return dtd; }; - Verschiebe den Stil in HTML und den JavaScript-Stil in CSS-Klassen; verwende Klassen in HTML und JavaScript anstelle von direkten Stilen.
ECMAScript 5-Kompatibilität
Verwende nach Möglichkeit ES5-Methoden, insbesondere die Array-Methoden map, filter und forEach, um die tägliche Entwicklung zu vereinfachen. In älteren IE-Browsern bindeES5-shimein. Oder du kannst auch erwägen,underscore、lodashgängige Hilfsbibliotheken.
- ReferenzKangaxES5Kompatibilitätstabelle。
Trennung von HTML, CSS und JavaScript
- Verwende HTML für die DOM-Struktur der Seite, CSS für Stile und JavaScript für dynamische DOM-Operationen. Vermische sie nicht in HTML.
- Trenne sie in verschiedene Dateitypen und verlinke die Dateien.
- HTML-, CSS- und JavaScript-Variablennamen müssen alle fachliche Bedeutung haben. CSS verwendet durch Bindestriche getrennte, durchgängig kleingeschriebene Namen, während JavaScript camelCase mit kleinem Anfangsbuchstaben verwendet.
- CSS kannBootstrap, Foundation und andere bekannte Responsive-Design-Frameworks einbinden. Verwende außerdem SASS- und LESS-Tools, um CSS zu schreiben.
- Für CSS und JavaScript wird empfohlen, sie in einer einzigen Datei zusammenzuführen, um die Anzahl der Ajax-Verbindungen zu reduzieren. Du kannst auch die Lademethode AMD (Require.js) einführen.
- Für die meisten internen Unternehmensmanagementsysteme kannst du versuchen, Frontend-MVC-Frameworkseinzusetzen, um Code zu organisieren. Zum Beispiel Angular, React + flux-Architektur, Knockout usw.
- Aus Kompatibilitätsgründen kannst duModernizrSpezifikationsbibliotheken zur Unterstützung verwenden.
jsHint verwenden
- Es wird empfohlen, in Front-End-Projektenjshint-Plugins einzuführen, um die Codierungsstandards des Projekts zu vereinheitlichen. Außerdem sollte ein vollständiger Satz IDE-Konfigurationen vorhanden sein.
- Hinweis: jshint erfordert die Einführung von nodejs-Tools, grunt- oder gulp-Plugins. Ein privater nodejs-npm-Server auf Unternehmensebene wird empfohlen.
Front-End-Tools
- Front-End-Tool zur Verwaltung von JavaScript-Paketen von Drittanbietern bower (
bower install jQuery), bower kann Abhängigkeitsauflösung, Download, Upgrade-Verwaltung usw. für Bibliotheken von Drittanbietern implementieren. Es wird empfohlen, einen privaten bower-Server auf Unternehmensebene einzurichten. - Für Front-End-Build-Tools können grunt- oder gulp-Tools verwendet werden, um alle Front-End-Aufgaben wie html-, css-, js-Komprimierung, Validierung, Tests, Dateizusammenführung, watch und liveload zu implementieren. Ein privater nodejs-npm-Server auf Unternehmensebene wird empfohlen.
- Front-End-Entwicklungs-IDE: WebStorm (Idea) und Sublime sind die besten. Das Projektteam sollte eine einheitliche IDE verwenden. Eine einheitliche IDE-Konfiguration ist sehr wichtig.
Ähnliche Artikel
- Javascript-Codierungsstandards
- Die beliebtesten JavaScript-Codestandards
- JavaScript-Codestilrichtlinie
Quelle: http://greengerong.github.io/blog/2015/05/09/qian-duan-javascriptgui-fan