Une approche plutôt raisonnable de JavaScript
Remarque : ce guide suppose que vous utilisez Babel et nécessite que vous utilisiez babel-preset-airbnb ou l'équivalent. Cela suppose également que vous installez des cales/polyfills dans votre application, avec des cales de navigateur Airbnb ou l'équivalent.
Ce guide est également disponible dans d'autres langues. Voir la traduction
Autres guides de style
1.1 Primitives : Lorsque vous accédez à un type primitif vous travaillez directement sur sa valeur.
string
number
boolean
null
undefined
symbol
bigint
const foo = 1 ;
let bar = foo ;
bar = 9 ;
console . log ( foo , bar ) ; // => 1, 9
1.2 Complexe : Lorsque vous accédez à un type complexe vous travaillez sur une référence à sa valeur.
object
array
function
const foo = [ 1 , 2 ] ;
const bar = foo ;
bar [ 0 ] = 9 ;
console . log ( foo [ 0 ] , bar [ 0 ] ) ; // => 9, 9
⬆ retour en haut
2.1 Utilisez const
pour toutes vos références ; évitez d'utiliser var
. eslint : prefer-const
, no-const-assign
Pourquoi? Cela garantit que vous ne pouvez pas réaffecter vos références, ce qui peut entraîner des bugs et rendre le code difficile à comprendre.
// bad
var a = 1 ;
var b = 2 ;
// good
const a = 1 ;
const b = 2 ;
2.2 Si vous devez réaffecter des références, utilisez let
au lieu de var
. eslint : no-var
Pourquoi?
let
est limité à un bloc plutôt qu'à une fonction commevar
.
// bad
var count = 1 ;
if ( true ) {
count += 1 ;
}
// good, use the let.
let count = 1 ;
if ( true ) {
count += 1 ;
}
2.3 Notez que let
et const
ont une portée de bloc, alors que var
est une portée de fonction.
// 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
Dans le code ci-dessus, vous pouvez voir que référencer a
et b
produira une ReferenceError, tandis que c
contient le numéro. En effet, a
et b
sont limités à un bloc, tandis que c
est limité à la fonction conteneur.
⬆ retour en haut
3.1 Utilisez la syntaxe littérale pour la création d'objets. eslint : no-new-object
// bad
const item = new Object ( ) ;
// good
const item = { } ;
3.2 Utilisez des noms de propriétés calculés lors de la création d'objets avec des noms de propriétés dynamiques.
Pourquoi? Ils permettent de définir toutes les propriétés d'un objet en un seul endroit.
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 Utilisez le raccourci de la méthode objet. 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 Utiliser un raccourci de valeur de propriété. eslint : object-shorthand
Pourquoi? Il est plus court et descriptif.
const lukeSkywalker = 'Luke Skywalker' ;
// bad
const obj = {
lukeSkywalker : lukeSkywalker ,
} ;
// good
const obj = {
lukeSkywalker ,
} ;
3.5 Regroupez vos propriétés abrégées au début de votre déclaration d'objet.
Pourquoi? Il est plus facile de savoir quelles propriétés utilisent le raccourci.
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 Ne citer que les propriétés qui sont des identifiants invalides. eslint : quote-props
Pourquoi? En général, nous le considérons subjectivement plus facile à lire. Il améliore la coloration syntaxique et est également plus facilement optimisé par de nombreux moteurs JS.
// bad
const bad = {
'foo' : 3 ,
'bar' : 4 ,
'data-blah' : 5 ,
} ;
// good
const good = {
foo : 3 ,
bar : 4 ,
'data-blah' : 5 ,
} ;
3.7 N'appelez pas directement les méthodes Object.prototype
, telles que hasOwnProperty
, propertyIsEnumerable
et isPrototypeOf
. eslint : no-prototype-builtins
Pourquoi? Ces méthodes peuvent être masquées par les propriétés de l'objet en question - considérez
{ hasOwnProperty: false }
- ou l'objet peut être un objet nul (Object.create(null)
). Dans les navigateurs modernes prenant en charge ES2022, ou avec un polyfill tel que https://npmjs.com/object.hasown,Object.hasOwn
peut également être utilisé comme alternative àObject.prototype.hasOwnProperty.call
.
// 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 Préférez la syntaxe de répartition d'objet à Object.assign
pour les objets à copie superficielle. Utilisez la syntaxe des paramètres object rest pour obtenir un nouvel objet avec certaines propriétés omises. 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 }
⬆ retour en haut
4.1 Utilisez la syntaxe littérale pour la création de tableaux. eslint : no-array-constructor
// bad
const items = new Array ( ) ;
// good
const items = [ ] ;
4.2 Utilisez Array#push au lieu d'une affectation directe pour ajouter des éléments à un tableau.
const someStack = [ ] ;
// bad
someStack [ someStack . length ] = 'abracadabra' ;
// good
someStack . push ( 'abracadabra' ) ;
4.3 Utiliser des tableaux de tableaux ...
pour copier des tableaux.
// 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 Pour convertir un objet itérable en tableau, utilisez spreads ...
au lieu de Array.from
const foo = document . querySelectorAll ( '.foo' ) ;
// good
const nodes = Array . from ( foo ) ;
// best
const nodes = [ ... foo ] ;
4.5 Utilisez Array.from
pour convertir un objet de type tableau en tableau.
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 Utilisez Array.from
au lieu de spread ...
pour le mappage sur les itérables, car cela évite de créer un tableau intermédiaire.
// bad
const baz = [ ... foo ] . map ( bar ) ;
// good
const baz = Array . from ( foo , bar ) ;
4.7 Utilisez les instructions return dans les rappels de méthodes de tableau. Vous pouvez omettre le retour si le corps de la fonction consiste en une seule instruction renvoyant une expression sans effets secondaires, conformément à 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 Utiliser des sauts de ligne après avoir ouvert les crochets d'un tableau et avant de fermer les crochets d'un tableau, si un tableau comporte plusieurs lignes
// 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 ,
] ;
⬆ retour en haut
5.1 Utiliser la déstructuration d'objet lors de l'accès et de l'utilisation de plusieurs propriétés d'un objet. eslint : prefer-destructuring
Pourquoi? La déstructuration vous évite de créer des références temporaires pour ces propriétés et d'accéder de manière répétitive à l'objet. L'accès répété aux objets crée un code plus répétitif, nécessite plus de lecture et crée plus de possibilités d'erreurs. La déstructuration d'objets fournit également un site unique de définition de la structure d'objet utilisée dans le bloc, plutôt que de nécessiter la lecture de l'intégralité du bloc pour déterminer ce qui est utilisé.
// 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 Utiliser la déstructuration de tableaux. 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 Utilisez la déstructuration d'objets pour plusieurs valeurs de retour, pas la déstructuration de tableaux.
Pourquoi? Vous pouvez ajouter de nouvelles propriétés au fil du temps ou modifier l'ordre des choses sans interrompre les sites d'appel.
// 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 ) ;
⬆ retour en haut
6.1 Utilisez des guillemets simples ''
pour les chaînes. 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 Les chaînes qui font dépasser 100 caractères sur la ligne ne doivent pas être écrites sur plusieurs lignes en utilisant la concaténation de chaînes.
Pourquoi? Les chaînes brisées sont difficiles à utiliser et rendent le code moins consultable.
// 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 Lors de la création de chaînes par programme, utilisez des chaînes de modèle au lieu de la concaténation. eslint : prefer-template
template-curly-spacing
Pourquoi? Les chaînes de modèles vous offrent une syntaxe lisible et concise avec des nouvelles lignes appropriées et des fonctionnalités d'interpolation de chaînes.
// 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()
sur une chaîne ; cela ouvre trop de vulnérabilités. eslint : no-eval
6.5 N'échappez pas inutilement les caractères dans les chaînes. eslint : no-useless-escape
Pourquoi? Barres obliques inverses