Dies sind Styleguides, die mir gefallen:
Zusätzlich gibt es zwei Styleguides, die ins Meta gehen
Dieser Abschnitt behandelt einige allgemeine Tipps zum Schreiben von Code.
var-Anweisungen geschrieben werdenDie zweite Regel ist, dass Sie, wenn Sie einem bestehenden Projekt beitreten, dessen Regeln strikt befolgen sollten (auch wenn Sie ihnen nicht zustimmen).
Für den größten Teil des Codes ist die Zeit, die zum Lesen benötigt wird, viel größer als die Zeit, die zum Schreiben benötigt wird. Es ist daher wichtig, ersteres so einfach wie möglich zu gestalten. Hier sind einige Richtlinien dafür
redBalloon leichter zu lesen als rdBlln.Die meisten Codebasen sind voller neuer Ideen und Konzepte. Das bedeutet, dass Sie diese Ideen und Konzepte lernen müssen, wenn Sie mit einer Codebasis arbeiten möchten. Im Gegensatz zu Lehrbüchern besteht die zusätzliche Herausforderung bei Code darin, dass die Leute ihn nicht linear lesen werden. Sie werden irgendwo einsteigen und grob verstehen können, was vor sich geht. Drei Teile einer Codebasis helfen
Viel Klugheit wird auf diese Optimierungen gerichtet. Normalerweise brauchen Sie sie jedoch nicht. Einerseits werden JavaScript-Engines immer intelligenter und optimieren automatisch die Geschwindigkeit von Code, der etablierten Mustern folgt. Andererseits schreiben Minifier-Tools (Kapitel 32) Ihren Code neu, sodass er so klein wie möglich ist. In beiden Fällen sind Tools für Sie clever, damit Sie es nicht sein müssen.
Manchmal haben Sie keine andere Wahl, als die Leistung Ihres Codes zu optimieren. Wenn Sie dies tun, stellen Sie sicher, dass Sie die richtigen Teile messen und optimieren. In Browsern beziehen sich die Probleme oft auf DOM und HTML und nicht auf die Sprache selbst.
Eine Mehrheit von JavaScript-Programmierern stimmt den folgenden Best Practices zu:
Verwenden Sie immer strikte Gleichheit (===) und strikte Ungleichheit (!==). Ich empfehle, von dieser Regel nie abzuweichen. Ich bevorzuge sogar die erste der beiden folgenden Bedingungen, obwohl sie äquivalent sind:
if(x!==undefined&&x!==null)...// my choiceif(x!=null)...// equivalent
In Sprachen, in denen Klammern Codeblöcke abgrenzen, bestimmt ein Klammerstil, wo Sie diese Klammern platzieren. Zwei Klammerstile sind in C-ähnlichen Sprachen (wie Java und JavaScript) am gebräuchlichsten: Allman-Stil und 1TBS.
// Allman brace stylefunctionfoo(x,y,z){if(x){a();}else{b();c();}}
// One True Brace Stylefunctionfoo(x,y,z){if(x){a();}else{b();c();}}
1TBS ist eine Variante des (älteren) K&R (Kernighan und Ritchie)-Stils.[21] Im K&R-Stil werden Funktionen im Allman-Stil geschrieben und Klammern weggelassen, wo sie nicht notwendig sind – zum Beispiel um einzeilige then-Fälle
// K&R brace stylefunctionfoo(x,y,z){if(x)a();else{b();c();}}
Der De-facto-Standard in der JavaScript-Welt ist 1TBS. Er wurde von Java übernommen und die meisten Styleguides empfehlen ihn. Ein Grund dafür ist objektiv. Wenn Sie ein Objektliteral zurückgeben, müssen Sie die öffnende Klammer in dieselbe Zeile wie das Schlüsselwort return setzen, wie hier (andernfalls fügt die automatische Semikolon-Einfügung ein Semikolon nach return ein, was bedeutet, dass nichts zurückgegeben wird; siehe Fallstrick: ASI kann unerwartet Anweisungen trennen)
return{name:'Jane'};
Offensichtlich ist ein Objektliteral kein Codeblock, aber die Dinge sehen konsistenter aus, und Sie machen weniger Fehler, wenn beides auf die gleiche Weise formatiert ist.
Mein persönlicher Stil und meine Vorliebe sind
Als Ausnahme lasse ich Klammern weg, wenn eine Anweisung in einer einzigen Zeile geschrieben werden kann. Zum Beispiel
if(x)returnx;
Mehrere Konstruktoren erzeugen Objekte, die auch durch Literale erstellt werden können. Letzteres ist normalerweise die bessere Wahl:
varobj=newObject();// novarobj={};// yesvararr=newArray();// novararr=[];// yesvarregex=newRegExp('abc');// avoid if possiblevarregex=/abc/;// yes
Verwenden Sie niemals den Konstruktor Array, um ein Array mit gegebenen Elementen zu erstellen. Initialisieren eines Arrays mit Elementen (vermeiden!) erklärt, warum
vararr=newArray('a','b','c');// never evervararr=['a','b','c'];// yes
Dieser Abschnitt sammelt Beispiele für nicht empfohlene Klugheit.
Verschachteln Sie denBedingungsoperator nicht:
// Don’t:returnx===0?'red':x===1?'green':'blue';// Better:if(x===0){return'red';}elseif(x===1){return'green';}else{return'blue';}// Best:switch(x){case0:return'red';case1:return'green';default:return'blue';}
Kürzen Sie if-Anweisungen nicht durch logische Operatoren:
foo&&bar();// noif(foo)bar();// yesfoo||bar();// noif(!foo)bar();// yes
Verwenden Sie, wenn möglich, den Inkrementoperator (++) und den Dekrementoperator (--) als Anweisungen; verwenden Sie sie nicht als Ausdrücke. In letzterem Fall geben sie einen Wert zurück, und obwohl es eine Eselsbrücke gibt, müssen Sie immer noch nachdenken, um herauszufinden, was vor sich geht:
// Unsure: what is happening?return++foo;// Easy to understand++foo;returnfoo;
if(x===void0)x=0;// not necessary in ES5if(x===undefined)x=0;// preferable
Ab ECMAScript 5 ist die zweite Methode besser. Ändern von undefined erklärt, warum.
returnx>>0;// noreturnMath.round(x);// yes
Der Shift-Operator kann verwendet werden, um eine Zahl in eine Ganzzahl umzuwandeln. Es ist jedoch normalerweise besser, eine explizitere Alternative wie Math.round() zu verwenden. Umwandlung in eine Ganzzahl gibt einen Überblick über alle Möglichkeiten der Umwandlung in eine Ganzzahl.
Manchmal kann man in JavaScript clever sein – wenn die Klugheit zu einem etablierten Muster geworden ist.
Die Verwendung des Oder-Operators (||), um Standardwerte bereitzustellen, ist ein gängiges Muster – zum Beispiel für Parameter:
functionf(x){x=x||0;...}
Für Details und weitere Beispiele konsultieren Sie bitte Muster: Bereitstellen eines Standardwerts.
Wenn Sie Methoden generisch verwenden, können Sie Object.prototype als {} abkürzen. Die folgenden beiden Ausdrücke sind äquivalent:
Object.prototype.hasOwnProperty.call(obj,propKey){}.hasOwnProperty.call(obj,propKey)
Und Array.prototype kann als [] abgekürzt werden:
Array.prototype.slice.call(arguments)[].slice.call(arguments)
Ich bin hier zwiegespalten. Es ist ein Hack (Sie greifen über eine Instanz auf eine Prototyp-Eigenschaft zu). Aber es reduziert Unordnung, und ich erwarte, dass Engines dieses Muster irgendwann optimieren werden.
Nachgestellte Kommas in Objektliteralen sind in ECMAScript 5 legal:
varobj={first:'Jane',last:'Doe',// legal: trailing comma};
ECMAScript 5 erlaubt es Ihnen auch, reservierte Wörter (wie new) als Eigenschaftsschlüssel zu verwenden:
> var obj = { new: 'abc' };
> obj.new
'abc'Betrachten wir einige Konventionen, die mir gefallen und die etwas umstrittener sind.
Wir beginnen mit syntaktischen Konventionen
Ich mag relativ dichten Whitespace. Das Modell ist geschriebenes Englisch: Es gibt keine Leerzeichen nach einer öffnenden Klammer und vor einer schließenden Klammer. Und es gibt Leerzeichen nach Kommas:
varresult=foo('a','b');vararr=[1,2,3];if(flag){...}
Für anonyme Funktionen befolge ich die Regel von Douglas Crockford, nach dem Schlüsselwort function ein Leerzeichen zu setzen. Die Begründung ist, dass dies so aussieht, wie ein benannter Funktionsausdruck aussieht, wenn Sie den Namen entfernen
functionfoo(arg){...}// named function expressionfunction(arg){...}// anonymous function expression
Dies hilft beim Lesen, da der Geltungsbereich des Operators leichter zu erkennen ist:
returnresult?result:theDefault;// noreturn(result?result:theDefault);// yes
Als Nächstes behandle ich Konventionen für Variablen
Ich deklariere nicht mehrere Variablen mit einer einzigen Deklaration:
// novarfoo=3,bar=2,baz;// yesvarfoo=3;varbar=2;varbaz;
Die Vorteile dieses Ansatzes sind, dass das Löschen, Einfügen und Umordnen von Zeilen einfacher ist und die Zeilen automatisch korrekt eingerückt werden.
var-Deklarationen block-scoped. Mit anderen Worten, Sie können eine Variable in dem Kontext deklarieren, in dem sie verwendet wird (innerhalb einer Schleife, innerhalb eines then-Blocks oder eines else-Blocks usw.). Diese Art der lokalen Kapselung macht ein Codefragment isoliert leichter verständlich. Es ist auch einfacher, das Codefragment zu entfernen oder woandershin zu verschieben.Als Ergänzung zur vorherigen Regel: Deklarieren Sie nicht dieselbe Variable zweimal, in zwei verschiedenen Blöcken. Zum Beispiel
// Don’t do thisif(v){varx=v;}else{varx=10;}doSomethingWith(x);
Der vorherige Code hat denselben Effekt und dieselbe Absicht wie der folgende Code, weshalb er so geschrieben werden sollte
varx;if(v){x=v;}else{x=10;}doSomethingWith(x);
Nun behandeln wir Konventionen bezüglich Objektorientierung.
Ich empfehle Ihnen,
new, wenn Sie eine Instanz erstellen.Die Hauptvorteile sind
Bei Konstruktoren ist es wichtig, den Strict Mode zu verwenden, da er Sie vor dem Vergessen des new-Operators zur Instanziierung schützt. Und Sie sollten sich bewusst sein, dass Sie in einem Konstruktor jedes Objekt zurückgeben können. Weitere Tipps zur Verwendung von Konstruktoren werden in Tipps zur Implementierung von Konstruktoren erwähnt.
Ich finde, dass eine solche Konstruktoraufrufung mit Klammern sauberer aussieht
varfoo=newFoo;// novarfoo=newFoo();// yes
Verwenden Sie Klammern, damit sich zwei Operatoren nicht gegenseitig überlagern – das Ergebnis ist nicht immer das, was Sie vielleicht erwarten:
> false && true || true true > false && (true || true) false > (false && true) || true true
instanceof ist besonders knifflig
> ! {} instanceof Array
false
> (!{}) instanceof Array
false
> !({} instanceof Array)
trueMethodenaufrufe nach einem Konstruktor finde ich jedoch unproblematisch
newFoo().bar().baz();// ok(newFoo()).bar().baz();// not necessary
Dieser Abschnitt sammelt verschiedene Tipps
Konvertieren Sie einen Wert in einen Typ über Boolean, Number, String(), Object() (als Funktionen verwendet – verwenden Sie diese Funktionen niemals als Konstruktoren). Die Begründung ist, dass diese Konvention beschreibender ist:
> +'123' // no
123
> Number('123') // yes
123
> ''+true // no
'true'
> String(true) // yes
'true'this als impliziten Parameter// Avoid:functionhandler(){this.logError(...);}// Prefer:functionhandler(context){context.logError(...);}
in und hasOwnProperty (siehe Iteration und Erkennung von Eigenschaften)Dies ist selbsterklärender und sicherer als der Vergleich mit undefined oder die Prüfung auf Wahrheitswerte
// All properties:if(obj.foo)// noif(obj.foo!==undefined)// noif('foo'inobj)...// yes// Own properties:if(obj.hasOwnProperty('foo'))...// risky for arbitrary objectsif(Object.prototype.hasOwnProperty.call(obj,'foo'))...// safe
Wenn Sie eine Stilfrage in Betracht ziehen, fragen Sie sich: Was macht meinen Code leichter verständlich? Widerstehen Sie der Versuchung, schlau zu sein, und überlassen Sie die meiste mechanische Klugheit JavaScript-Engines und Minifiern (siehe Kapitel 32).
[21] Manche Leute sagen sogar, dass sie Synonyme sind, dass 1TBS eine scherzhafte Bezeichnung für K&R ist.