Ein größtenteils vernünftiger Ansatz für JavaScript
Hinweis : In diesem Handbuch wird davon ausgegangen, dass Sie Babel verwenden, und es ist erforderlich, dass Sie babel-preset-airbnb oder ein gleichwertiges Produkt verwenden. Es wird außerdem davon ausgegangen, dass Sie Shims/Polyfills in Ihrer App installieren, mit Airbnb-Browser-Shims oder einem Äquivalent.
Dieser Leitfaden ist auch in anderen Sprachen verfügbar. Siehe Übersetzung
Andere Styleguides
1.1 Primitive : Wenn Sie auf einen Primitivtyp zugreifen, bearbeiten Sie direkt dessen Wert.
string
number
boolean
null
undefined
symbol
bigint
const foo = 1 ;
let bar = foo ;
bar = 9 ;
console . log ( foo , bar ) ; // => 1, 9
1.2 Komplex : Wenn Sie auf einen komplexen Typ zugreifen, arbeiten Sie an einer Referenz auf seinen Wert.
object
array
function
const foo = [ 1 , 2 ] ;
const bar = foo ;
bar [ 0 ] = 9 ;
console . log ( foo [ 0 ] , bar [ 0 ] ) ; // => 9, 9
⬆ zurück nach oben
2.1 Verwenden Sie const
für alle Ihre Referenzen; Vermeiden Sie die Verwendung von var
. eslint: prefer-const
, no-const-assign
Warum? Dadurch wird sichergestellt, dass Sie Ihre Referenzen nicht neu zuweisen können, was zu Fehlern und schwer verständlichem Code führen kann.
// bad
var a = 1 ;
var b = 2 ;
// good
const a = 1 ;
const b = 2 ;
2.2 Wenn Sie Referenzen neu zuweisen müssen, verwenden Sie let
anstelle von var
. eslint: no-var
Warum?
let
ist eher blockbezogen als funktionsbezogen wievar
.
// bad
var count = 1 ;
if ( true ) {
count += 1 ;
}
// good, use the let.
let count = 1 ;
if ( true ) {
count += 1 ;
}
2.3 Beachten Sie, dass sowohl let
als auch const
einen Blockbereich haben, während var
einen Funktionsbereich hat.
// const and let only exist in the blocks they are defined in.
{
let a = 1 ;
const b = 1 ;
var c = 1 ;
}
console . log ( a ) ; // ReferenceError
console . log ( b ) ; // ReferenceError
console . log ( c ) ; // Prints 1
Im obigen Code können Sie sehen, dass die Referenzierung von a
und b
einen ReferenceError erzeugt, während c
die Zahl enthält. Dies liegt daran, dass a
und b
blockbezogen sind, während c
auf die enthaltende Funktion beschränkt ist.
⬆ zurück nach oben
3.1 Verwenden Sie die Literalsyntax zur Objekterstellung. eslint: no-new-object
// bad
const item = new Object ( ) ;
// good
const item = { } ;
3.2 Verwenden Sie berechnete Eigenschaftsnamen, wenn Sie Objekte mit dynamischen Eigenschaftsnamen erstellen.
Warum? Sie ermöglichen es Ihnen, alle Eigenschaften eines Objekts an einem Ort zu definieren.
function getKey ( k ) {
return `a key named ${ k } ` ;
}
// bad
const obj = {
id : 5 ,
name : 'San Francisco' ,
} ;
obj [ getKey ( 'enabled' ) ] = true ;
// good
const obj = {
id : 5 ,
name : 'San Francisco' ,
[ getKey ( 'enabled' ) ] : true ,
} ;
3.3 Verwenden Sie die Kurzform der Objektmethode. eslint: object-shorthand
// bad
const atom = {
value : 1 ,
addValue : function ( value ) {
return atom . value + value ;
} ,
} ;
// good
const atom = {
value : 1 ,
addValue ( value ) {
return atom . value + value ;
} ,
} ;
3.4 Verwenden Sie die Abkürzung für den Eigenschaftswert. eslint: object-shorthand
Warum? Es ist kürzer und beschreibender.
const lukeSkywalker = 'Luke Skywalker' ;
// bad
const obj = {
lukeSkywalker : lukeSkywalker ,
} ;
// good
const obj = {
lukeSkywalker ,
} ;
3.5 Gruppieren Sie Ihre Kurzeigenschaften am Anfang Ihrer Objektdeklaration.
Warum? Es ist einfacher zu erkennen, welche Eigenschaften die Abkürzung verwenden.
const anakinSkywalker = 'Anakin Skywalker' ;
const lukeSkywalker = 'Luke Skywalker' ;
// bad
const obj = {
episodeOne : 1 ,
twoJediWalkIntoACantina : 2 ,
lukeSkywalker ,
episodeThree : 3 ,
mayTheFourth : 4 ,
anakinSkywalker ,
} ;
// good
const obj = {
lukeSkywalker ,
anakinSkywalker ,
episodeOne : 1 ,
twoJediWalkIntoACantina : 2 ,
episodeThree : 3 ,
mayTheFourth : 4 ,
} ;
3.6 Zitieren Sie nur Eigenschaften, die ungültige Bezeichner sind. eslint: quote-props
Warum? Generell halten wir es für subjektiv leichter lesbar. Es verbessert die Syntaxhervorhebung und lässt sich auch von vielen JS-Engines einfacher optimieren.
// bad
const bad = {
'foo' : 3 ,
'bar' : 4 ,
'data-blah' : 5 ,
} ;
// good
const good = {
foo : 3 ,
bar : 4 ,
'data-blah' : 5 ,
} ;
3.7 Rufen Sie Object.prototype
-Methoden nicht direkt auf, z. B. hasOwnProperty
, propertyIsEnumerable
und isPrototypeOf
. eslint: no-prototype-builtins
Warum? Diese Methoden können durch Eigenschaften des betreffenden Objekts überschattet werden – siehe
{ hasOwnProperty: false }
– oder das Objekt kann ein Nullobjekt sein (Object.create(null)
). In modernen Browsern, die ES2022 unterstützen, oder mit einem Polyfill wie https://npmjs.com/object.hasown kannObject.hasOwn
auch als Alternative zuObject.prototype.hasOwnProperty.call
verwendet werden.
// bad
console . log ( object . hasOwnProperty ( key ) ) ;
// good
console . log ( Object . prototype . hasOwnProperty . call ( object , key ) ) ;
// better
const has = Object . prototype . hasOwnProperty ; // cache the lookup once, in module scope.
console . log ( has . call ( object , key ) ) ;
// best
console . log ( Object . hasOwn ( object , key ) ) ; // only supported in browsers that support ES2022
/* or */
import has from 'has' ; // https://www.npmjs.com/package/has
console . log ( has ( object , key ) ) ;
/* or */
console . log ( Object . hasOwn ( object , key ) ) ; // https://www.npmjs.com/package/object.hasown
3.8 Bevorzugen Sie die Object-Spread-Syntax gegenüber Object.assign
um Objekte flach zu kopieren. Verwenden Sie die Objekt-Rest-Parametersyntax, um ein neues Objekt zu erhalten, bei dem bestimmte Eigenschaften weggelassen werden. eslint: prefer-object-spread
// very bad
const original = { a : 1 , b : 2 } ;
const copy = Object . assign ( original , { c : 3 } ) ; // this mutates `original` ಠ_ಠ
delete copy . a ; // so does this
// bad
const original = { a : 1 , b : 2 } ;
const copy = Object . assign ( { } , original , { c : 3 } ) ; // copy => { a: 1, b: 2, c: 3 }
// good
const original = { a : 1 , b : 2 } ;
const copy = { ... original , c : 3 } ; // copy => { a: 1, b: 2, c: 3 }
const { a , ... noA } = copy ; // noA => { b: 2, c: 3 }
⬆ zurück nach oben
4.1 Verwenden Sie die Literalsyntax für die Array-Erstellung. eslint: no-array-constructor
// bad
const items = new Array ( ) ;
// good
const items = [ ] ;
4.2 Verwenden Sie Array#push anstelle der direkten Zuweisung, um Elemente zu einem Array hinzuzufügen.
const someStack = [ ] ;
// bad
someStack [ someStack . length ] = 'abracadabra' ;
// good
someStack . push ( 'abracadabra' ) ;
4.3 Verwenden Sie Array-Spreads ...
um Arrays zu kopieren.
// bad
const len = items . length ;
const itemsCopy = [ ] ;
let i ;
for ( i = 0 ; i < len ; i += 1 ) {
itemsCopy [ i ] = items [ i ] ;
}
// good
const itemsCopy = [ ... items ] ;
4.4 Um ein iterierbares Objekt in ein Array umzuwandeln, verwenden Sie spreads ...
anstelle von Array.from
const foo = document . querySelectorAll ( '.foo' ) ;
// good
const nodes = Array . from ( foo ) ;
// best
const nodes = [ ... foo ] ;
4.5 Verwenden Sie Array.from
zum Konvertieren eines Array-ähnlichen Objekts in ein Array.
const arrLike = { 0 : 'foo' , 1 : 'bar' , 2 : 'baz' , length : 3 } ;
// bad
const arr = Array . prototype . slice . call ( arrLike ) ;
// good
const arr = Array . from ( arrLike ) ;
4.6 Verwenden Sie Array.from
anstelle von spread ...
für die Zuordnung über Iterables, da dadurch die Erstellung eines Zwischenarrays vermieden wird.
// bad
const baz = [ ... foo ] . map ( bar ) ;
// good
const baz = Array . from ( foo , bar ) ;
4.7 Verwenden Sie Return-Anweisungen in Rückrufen von Array-Methoden. Es ist in Ordnung, die Rückgabe wegzulassen, wenn der Funktionskörper aus einer einzelnen Anweisung besteht, die einen Ausdruck ohne Nebenwirkungen zurückgibt, gemäß 8.2. eslint: array-callback-return
// good
[ 1 , 2 , 3 ] . map ( ( x ) => {
const y = x + 1 ;
return x * y ;
} ) ;
// good
[ 1 , 2 , 3 ] . map ( ( x ) => x + 1 ) ;
// bad - no returned value means `acc` becomes undefined after the first iteration
[ [ 0 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] ] . reduce ( ( acc , item , index ) => {
const flatten = acc . concat ( item ) ;
} ) ;
// good
[ [ 0 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] ] . reduce ( ( acc , item , index ) => {
const flatten = acc . concat ( item ) ;
return flatten ;
} ) ;
// bad
inbox . filter ( ( msg ) => {
const { subject , author } = msg ;
if ( subject === 'Mockingbird' ) {
return author === 'Harper Lee' ;
} else {
return false ;
}
} ) ;
// good
inbox . filter ( ( msg ) => {
const { subject , author } = msg ;
if ( subject === 'Mockingbird' ) {
return author === 'Harper Lee' ;
}
return false ;
} ) ;
4.8 Verwenden Sie Zeilenumbrüche nach dem Öffnen von Array-Klammern und vor dem Schließen von Array-Klammern, wenn ein Array mehrere Zeilen hat
// bad
const arr = [
[ 0 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] ,
] ;
const objectInArray = [ {
id : 1 ,
} , {
id : 2 ,
} ] ;
const numberInArray = [
1 , 2 ,
] ;
// good
const arr = [ [ 0 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] ] ;
const objectInArray = [
{
id : 1 ,
} ,
{
id : 2 ,
} ,
] ;
const numberInArray = [
1 ,
2 ,
] ;
⬆ zurück nach oben
5.1 Verwenden Sie die Objektdestrukturierung, wenn Sie auf mehrere Eigenschaften eines Objekts zugreifen und diese verwenden. eslint: prefer-destructuring
Warum? Die Destrukturierung erspart Ihnen die Erstellung temporärer Referenzen für diese Eigenschaften und den wiederholten Zugriff auf das Objekt. Wiederholter Objektzugriff führt zu mehr sich wiederholendem Code, erfordert mehr Leseaufwand und schafft mehr Möglichkeiten für Fehler. Die Destrukturierung von Objekten bietet außerdem eine einzige Definitionsstelle für die Objektstruktur, die im Block verwendet wird, anstatt den gesamten Block lesen zu müssen, um zu bestimmen, was verwendet wird.
// bad
function getFullName ( user ) {
const firstName = user . firstName ;
const lastName = user . lastName ;
return ` ${ firstName } ${ lastName } ` ;
}
// good
function getFullName ( user ) {
const { firstName , lastName } = user ;
return ` ${ firstName } ${ lastName } ` ;
}
// best
function getFullName ( { firstName , lastName } ) {
return ` ${ firstName } ${ lastName } ` ;
}
5.2 Array-Destrukturierung verwenden. eslint: prefer-destructuring
const arr = [ 1 , 2 , 3 , 4 ] ;
// bad
const first = arr [ 0 ] ;
const second = arr [ 1 ] ;
// good
const [ first , second ] = arr ;
5.3 Verwenden Sie die Objektdestrukturierung für mehrere Rückgabewerte, nicht die Array-Destrukturierung.
Warum? Sie können im Laufe der Zeit neue Eigenschaften hinzufügen oder die Reihenfolge der Dinge ändern, ohne dass Anrufseiten unterbrochen werden.
// bad
function processInput ( input ) {
// then a miracle occurs
return [ left , right , top , bottom ] ;
}
// the caller needs to think about the order of return data
const [ left , __ , top ] = processInput ( input ) ;
// good
function processInput ( input ) {
// then a miracle occurs
return { left , right , top , bottom } ;
}
// the caller selects only the data they need
const { left , top } = processInput ( input ) ;
⬆ zurück nach oben
6.1 Verwenden Sie einfache Anführungszeichen ''
für Zeichenfolgen. eslint: quotes
// bad
const name = "Capt. Janeway" ;
// bad - template literals should contain interpolation or newlines
const name = `Capt. Janeway` ;
// good
const name = 'Capt. Janeway' ;
6.2 Zeichenfolgen, die dazu führen, dass die Zeile mehr als 100 Zeichen umfasst, sollten nicht mithilfe der Zeichenfolgenverkettung über mehrere Zeilen geschrieben werden.
Warum? Unterbrochene Zeichenfolgen sind mühsam zu bearbeiten und machen den Code weniger durchsuchbar.
// bad
const 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
const 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
const 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.' ;
6.3 Verwenden Sie beim programmgesteuerten Aufbau von Zeichenfolgen Vorlagenzeichenfolgen anstelle von Verkettungen. eslint: prefer-template
template-curly-spacing
Warum? Vorlagenzeichenfolgen bieten Ihnen eine lesbare, prägnante Syntax mit geeigneten Zeilenumbrüchen und Zeichenfolgeninterpolationsfunktionen.
// bad
function sayHi ( name ) {
return 'How are you, ' + name + '?' ;
}
// bad
function sayHi ( name ) {
return [ 'How are you, ' , name , '?' ] . join ( ) ;
}
// bad
function sayHi ( name ) {
return `How are you, ${ name } ?` ;
}
// good
function sayHi ( name ) {
return `How are you, ${ name } ?` ;
}
eval()
niemals für einen String; es öffnet zu viele Schwachstellen. eslint: no-eval
6.5 Escape-Zeichen in Zeichenfolgen nicht unnötig verwenden. eslint: no-useless-escape
Warum? Backslashes