Photo by Pankaj Patel on Unsplash
Guide de style JavaScript Airbnb()
Une approche raisonnable pour le JavaScript.
Autres guides de style
Traduit de Airbnb JavaScript Style Guide.
Types (Types)
- 1.1 Primitifs (Primitives) : Vous accédez aux types primitifs directement.
stringnumberbooleannullundefined
const foo = 1;
let bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 9
- 1.2 Complexes (Complex) : Vous accédez aux types complexes par référence (by reference).
objectarrayfunction
const foo = [1, 2];
const bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
Références (References)
- 2.1 Utilisez
constpour toutes vos références ; évitez d’utiliservar. eslint :prefer-const,no-const-assign
Pourquoi ? Cela garantit que vous ne pouvez pas réassigner vos références, ce qui peut entraîner des bugs et un code difficile à comprendre.
// bad
var a = 1;
var b = 2;
// good
const a = 1;
const b = 2;
- 2.2 Si vous devez réassigner des références, utilisez
letau lieu devar. eslint :no-varjscs :disallowVar
Pourquoi ?
leta une portée de bloc (block-scoped), tandis quevara une portée de fonction (function-scoped).
// bad
var count = 1;
if (true) {
count += 1;
}
// good, use the let.
let count = 1;
if (true) {
count += 1;
}
- 2.3 Notez que
letetconstont tous deux une portée de bloc.
// const et let n'existent qu'à l'intérieur des blocs où ils sont définis.
{
let a = 1;
const b = 1;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError
Objets (Objects)
- 3.1 Utilisez la syntaxe littérale pour la création d’objets. eslint rules :
no-new-object.
// bad
const item = new Object();
// good
const item = {};
- 3.2 N’utilisez pas de mots réservés comme clés. Cela ne fonctionnera pas sous IE8. Plus d’infos. Cependant, il est possible de les utiliser dans les modules ES6 et le code côté serveur. jscs :
disallowIdentifierNames
// bad
const superman = {
default: { clark: 'kent' },
private: true,
};
// good
const superman = {
defaults: { clark: 'kent' },
hidden: true,
};
- 3.3 Utilisez des synonymes lisibles à la place des mots réservés. jscs :
disallowIdentifierNames
// bad
const superman = {
class: 'alien',
};
// bad
const superman = {
klass: 'alien',
};
// good
const superman = {
type: 'alien',
};
- 3.4 Utilisez des noms de propriétés calculés (computed property names) lors de la création d’objets avec des noms de propriétés dynamiques.
Pourquoi ? Ils vous permettent de définir toutes les propriétés de l’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.5 Utilisez la notation abrégée pour les méthodes d’objet (object method shorthand). eslint :
object-shorthandjscs :requireEnhancedObjectLiterals
// bad
const atom = {
value: 1,
addValue: function (value) {
return atom.value + value;
},
};
// good
const atom = {
value: 1,
addValue(value) {
return atom.value + value;
},
};
- 3.6 Utilisez la notation abrégée pour les valeurs de propriété (property value shorthand). eslint :
object-shorthandjscs :requireEnhancedObjectLiterals
Pourquoi ? C’est plus court et plus descriptif.
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
lukeSkywalker: lukeSkywalker,
};
// good
const obj = {
lukeSkywalker,
};
- 3.7 Groupez vos notations abrégées au début de votre déclaration d’objet.
Pourquoi ? Il est plus facile de voir quelles propriétés utilisent la notation abrégée.
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.8 Ne mettez des guillemets qu’autour des propriétés qui sont des identifiants invalides. eslint :
quote-propsjscs :disallowQuotedKeysInObjects
Pourquoi ? En général, nous considérons que c’est subjectivement plus facile à lire. Cela améliore la coloration syntaxique et est également plus facile à optimiser 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,
};
Tableaux (Arrays)
- 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 Utilisez les spreads de tableau
...pour copier des tableaux.
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
- 4.4 Pour convertir un objet de type array (array-like object) en tableau, utilisez Array#from.
const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);
- 4.5 Utilisez des instructions de retour dans les callbacks de méthodes de tableau. Il est acceptable d’omettre le retour si le corps de la fonction consiste en une seule instruction suivant 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
const flat = {};
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
const flatten = memo.concat(item);
flat[index] = memo.concat(item);
});
// good
const flat = {};
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
const flatten = memo.concat(item);
flat[index] = flatten;
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;
});
Déstructuration (Destructuring)
- 5.1 Utilisez la déstructuration d’objet lorsque vous accédez et utilisez plusieurs propriétés d’un objet. jscs :
requireObjectDestructuring
Pourquoi ? La déstructuration vous évite de créer des références temporaires pour ces propriétés.
// 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 Utilisez la déstructuration de tableau. jscs :
requireArrayDestructuring
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’objet pour plusieurs valeurs de retour, pas la déstructuration de tableau.
Pourquoi ? Vous pouvez ajouter de nouvelles propriétés ou changer l’ordre des éléments sans casser les sites d’appel (call sites).
// 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, right } = processInput(input);
Chaînes de caractères (Strings)
- 6.1 Utilisez des apostrophes
''pour les chaînes de caractères. eslint :quotesjscs :validateQuoteMarks
// bad
const name = "Capt. Janeway";
// good
const name = 'Capt. Janeway';
- 6.2 Les chaînes de caractères qui font dépasser la ligne de 100 caractères ne doivent pas être écrites sur plusieurs lignes en utilisant la concaténation de chaînes.
- 6.3 Note : Si utilisé excessivement, les longues chaînes avec concaténation peuvent impacter les performances. jsPerf & Discussion.
// 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.4 Lors de la construction de chaînes de caractères par programmation, utilisez des template strings au lieu de la concaténation. eslint :
prefer-templatetemplate-curly-spacingjscs :requireTemplateStrings
Pourquoi ? Les template strings vous donnent une syntaxe lisible et concise avec des sauts de ligne 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}?`;
}
- 6.5 N’utilisez jamais
eval()sur une chaîne de caractères, cela ouvre trop de vulnérabilités.
Fonctions (Functions)
- 7.1 Utilisez des déclarations de fonction (function declarations) au lieu d’expressions de fonction (function expressions). jscs :
requireFunctionDeclarations
Pourquoi ? Les déclarations de fonction sont nommées, elles sont donc plus faciles à identifier dans les stack traces. De plus, les déclarations de fonction sont hissées (hoisted), contrairement aux expressions de fonction. Cette règle permet aux Fonctions Fléchées de remplacer complètement les expressions de fonction.
// bad
const foo = function () {
};
// good
function foo() {
}
- 7.2 IIFE : eslint :
wrap-iifejscs :requireParenthesesAroundIIFE
Pourquoi ? Une IIFE est une unité unique - envelopper la fonction et son appel entre parenthèses rend cela clair. Notez que dans un monde avec des modules, vous n’avez presque pas besoin d’IIFE.
// immediately-invoked function expression (IIFE)
(function () {
console.log('Welcome to the Internet. Please follow me.');
}());
-
7.3 Ne déclarez jamais une fonction dans un bloc non-fonctionnel (if, while, etc). Assignez la fonction à une variable à la place. Les navigateurs vous permettront de le faire, mais ils l’interprètent tous différemment. eslint :
no-loop-func -
7.4 Note : ECMA-262 définit un
bloccomme une liste d’instructions. Une déclaration de fonction n’est pas une instruction. Lire la note d’ECMA-262 sur ce problème.
// bad
if (currentUser) {
function test() {
console.log('Nope.');
}
}
// good
let test;
if (currentUser) {
test = () => {
console.log('Yup.');
};
}
- 7.5 Ne nommez jamais un paramètre
arguments. Cela prendra le pas sur l’objetargumentsqui est donné à chaque portée de fonction.
// bad
function nope(name, options, arguments) {
// ...stuff...
}
// good
function yup(name, options, args) {
// ...stuff...
}
- 7.6 N’utilisez jamais
arguments, optez pour la syntaxe rest...à la place.prefer-rest-params
Pourquoi ?
...rend explicite les arguments que vous souhaitez récupérer. De plus, les arguments rest sont un véritable Tableau, et pas seulement de type Array commearguments.
// bad
function concatenateAll() {
const args = Array.prototype.slice.call(arguments);
return args.join('');
}
// good
function concatenateAll(...args) {
return args.join('');
}
- 7.7 Utilisez la syntaxe des paramètres par défaut au lieu de modifier les arguments de la fonction.
// really bad
function handleThings(opts) {
// No! We shouldn't mutate function arguments.
// Double bad: if opts is false it will be set to an object which may
// be what you want but it can cause subtle bugs.
opts = opts || {};
// ...
}
// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
}
// good
function handleThings(opts = {}) {
// ...
}
- 7.8 Évitez les effets de bord avec les paramètres par défaut.
Pourquoi ? Ils sont déroutants à comprendre.
var b = 1;
// bad
function count(a = b++) {
console.log(a);
}
count(); // 1
count(); // 2
count(3); // 3
count(); // 3
- 7.9 Mettez toujours les paramètres par défaut en dernier.
// bad
function handleThings(opts = {}, name) {
// ...
}
// good
function handleThings(name, opts = {}) {
// ...
}
- 7.10 N’utilisez jamais le constructeur Function pour créer une nouvelle fonction.
Pourquoi ? Créer une fonction de cette manière évalue une chaîne de caractères de la même manière que eval(), ce qui ouvre des vulnérabilités.
// bad
var add = new Function('a', 'b', 'return a + b');
// still bad
var subtract = Function('a', 'b', 'return a - b');
- 7.11 Espacement dans une signature de fonction.
Pourquoi ? La cohérence est bonne, et vous ne devriez pas avoir à ajouter ou supprimer de l’espace lors de l’ajout ou de la suppression d’un nom.
// bad
const f = function(){};
const g = function (){};
const h = function() {};
// good
const x = function () {};
const y = function a() {};
- 7.12 Ne modifiez jamais les paramètres. eslint :
no-param-reassign
Pourquoi ? La manipulation d’objets passés en tant que paramètres peut provoquer des effets de bord indésirables chez l’appelant d’origine.
// bad
function f1(obj) {
obj.key = 1;
};
// good
function f2(obj) {
const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
};
- 7.13 Ne réassignez jamais les paramètres. eslint :
no-param-reassign
Pourquoi ? La réaffectation de paramètres peut entraîner un comportement inattendu, en particulier lors de l’accès à l’objet
arguments. Cela peut également causer des problèmes d’optimisation, en particulier dans V8.
```javascript
// bad
function f1(a) {
a = 1;
}
function f2(a) {
if (!a) { a = 1; }
}
// good
function f3(a) {
const b = a || 1;
}
function f4(a = 1) {
}
```
Fonctions Fléchées (Arrow Functions)
- 8.1 Lorsque vous devez utiliser une expression de fonction (comme lors du passage d’une fonction anonyme), utilisez la notation de fonction fléchée. eslint :
prefer-arrow-callback,arrow-spacingjscs :requireArrowFunctions
Pourquoi ? Cela crée une version de la fonction qui s’exécute dans le contexte de
this, ce qui est généralement ce que vous voulez, et c’est une syntaxe plus concise.
Pourquoi pas ? Si vous avez une fonction assez complexe, vous pouvez déplacer cette logique dans sa propre déclaration de fonction nommée.
// bad
[1, 2, 3].map(function (x) {
const y = x + 1;
return x * y;
});
// good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
- 8.2 Si le corps de la fonction consiste en une seule instruction retournant une expression sans effets de bord, omettez les accolades et utilisez le retour implicite. Sinon, conservez les accolades et utilisez une instruction
return. eslint :arrow-parens,arrow-body-stylejscs :disallowParenthesesAroundArrowParam,requireShorthandArrowFunctions
Pourquoi ? Sucre syntaxique (Syntactic sugar). C’est plus lisible lorsque plusieurs fonctions sont enchaînées ensemble.
Pourquoi pas ? Si vous prévoyez de retourner un objet.
// bad
[1, 2, 3].map(number => {
const nextNumber = number + 1;
`A string containing the ${nextNumber}.`;
});
// good
[1, 2, 3].map(number => `A string containing the ${number}.`);
// good
[1, 2, 3].map((number) => {
const nextNumber = number + 1;
return `A string containing the ${nextNumber}.`;
});
- 8.3 Si l’expression s’étend sur plusieurs lignes, enveloppez-la entre parenthèses pour une meilleure lisibilité.
Pourquoi ? Cela montre clairement où la fonction commence et se termine.
// bad
[1, 2, 3].map(number => 'As time went by, the string containing the ' +
`${number} became much longer. So we needed to break it over multiple ` +
'lines.'
);
// good
[1, 2, 3].map(number => (
`As time went by, the string containing the ${number} became much ` +
'longer. So we needed to break it over multiple lines.'
));
- 8.4 Si votre fonction prend un seul argument et n’utilise pas d’accolades, omettez les parenthèses. Sinon, incluez toujours des parenthèses autour des arguments. eslint :
arrow-parensjscs :disallowParenthesesAroundArrowParam
Pourquoi ? Moins d’encombrement visuel.
// bad
[1, 2, 3].map((x) => x * x);
// good
[1, 2, 3].map(x => x * x);
// good
[1, 2, 3].map(number => (
`A long string with the ${number}. It’s so long that we’ve broken it ` +
'over multiple lines!'
));
// bad
[1, 2, 3].map(x => {
const y = x + 1;
return x * y;
});
// good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
- 8.5 Évitez de confondre la syntaxe de la fonction fléchée (
=>) avec les opérateurs de comparaison (<=,>=). eslint :no-confusing-arrow
// bad
const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize;
// bad
const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize;
// good
const itemHeight = item => { return item.height > 256 ? item.largeSize : item.smallSize; }
Constructeurs (Constructors)
- 9.1 Utilisez toujours
class. Évitez de manipulerprototypedirectement.
Pourquoi ? La syntaxe
classest plus concise et plus facile à raisonner.
// bad
function Queue(contents = []) {
this._queue = [...contents];
}
Queue.prototype.pop = function () {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
// good
class Queue {
constructor(contents = []) {
this._queue = [...contents];
}
pop() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
}
- 9.2 Utilisez
extendspour l’héritage.
Pourquoi ? C’est un moyen intégré d’hériter de la fonctionnalité du prototype sans casser
instanceof.
// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function () {
return this._queue[0];
}
// good
class PeekableQueue extends Queue {
peek() {
return this._queue[0];
}
}
- 9.3 Les méthodes peuvent retourner
thispour aider au chaînage de méthodes (method chaining).
// bad
Jedi.prototype.jump = function () {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function (height) {
this.height = height;
};
const luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined
// good
class Jedi {
jump() {
this.jumping = true;
return this;
}
setHeight(height) {
this.height = height;
return this;
}
}
const luke = new Jedi();
luke.jump()
.setHeight(20);
- 9.4 Il est acceptable d’écrire une méthode toString() personnalisée, assurez-vous simplement qu’elle fonctionne correctement et ne provoque pas d’effets de bord.
class Jedi {
constructor(options = {}) {
this.name = options.name || 'no name';
}
getName() {
return this.name;
}
toString() {
return `Jedi - ${this.getName()}`;
}
}
- 9.5 Les classes ont un constructeur par défaut s’il n’est pas spécifié. Un constructeur vide ou un constructeur qui ne fait que déléguer à une classe parente est inutile.
no-useless-constructor
// bad
class Jedi {
constructor() {}
getName() {
return this.name;
}
}
// bad
class Rey extends Jedi {
constructor(...args) {
super(...args);
}
}
// good
class Rey extends Jedi {
constructor(...args) {
super(...args);
this.name = 'Rey';
}
}
Modules (Modules)
- 10.1 Utilisez toujours des modules (
import/export) plutôt qu’un système de modules non standard. Vous pouvez toujours transpiler vers votre système de modules préféré.
Pourquoi ? Les modules sont l’avenir, commençons à utiliser l’avenir maintenant.
// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide');
module.exports = AirbnbStyleGuide.es6;
// ok
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default AirbnbStyleGuide.es6;
// best
import { es6 } from './AirbnbStyleGuide';
export default es6;
- 10.2 N’utilisez pas d’importations avec des caractères génériques (wildcard imports).
Pourquoi ? Cela garantit que vous avez un seul export par défaut.
// bad
import * as AirbnbStyleGuide from './AirbnbStyleGuide';
// good
import AirbnbStyleGuide from './AirbnbStyleGuide';
- 10.3 Et n’exportez pas directement depuis un import.
Pourquoi ? Bien que l’écriture en une seule ligne soit concise, avoir une manière claire d’importer et une manière claire d’exporter rend les choses cohérentes.
// bad
// filename es6.js
export { es6 as default } from './airbnbStyleGuide';
// good
// filename es6.js
import { es6 } from './AirbnbStyleGuide';
export default es6;
Itérateurs et Générateurs (Iterators and Generators)
- 11.1 N’utilisez pas d’itérateurs. Préférez les fonctions d’ordre supérieur de JavaScript comme
map()etreduce()au lieu de boucles commefor-of. eslint :no-iterator
Pourquoi ? Cela impose notre règle d’immutabilité. Traiter avec des fonctions pures qui retournent des valeurs est plus facile à raisonner que les effets de bord.
eslint rules : no-iterator.
const numbers = [1, 2, 3, 4, 5];
// bad
let sum = 0;
for (let num of numbers) {
sum += num;
}
sum === 15;
// good
let sum = 0;
numbers.forEach(num => sum += num);
sum === 15;
// best (use the functional force)
const sum = numbers.reduce((total, num) => total + num, 0);
sum === 15;
- 11.2 N’utilisez pas de générateurs pour le moment.
Pourquoi ? Ils ne se transpilent pas encore bien en ES5.
Propriétés (Properties)
- 12.1 Utilisez la notation par point (dot notation) lors de l’accès aux propriétés. eslint :
dot-notationjscs :requireDotNotation
const luke = {
jedi: true,
age: 28,
};
// bad
const isJedi = luke['jedi'];
// good
const isJedi = luke.jedi;
- 12.2 Utilisez la notation par crochets
[]lors de l’accès aux propriétés avec une variable.
const luke = {
jedi: true,
age: 28,
};
function getProp(prop) {
return luke[prop];
}
const isJedi = getProp('jedi');
Variables (Variables)
- 13.1 Utilisez toujours
constouletpour déclarer des variables. Ne pas le faire entraînera des variables globales. Nous voulons éviter de polluer l’espace de noms global. Le Capitaine Planète nous a mis en garde contre cela.
// bad
superPower = new SuperPower();
// good
const superPower = new SuperPower();
- 13.2 Utilisez une déclaration
constouletpar variable. eslint :one-varjscs :disallowMultipleVarDecl
Pourquoi ? Il est plus facile d’ajouter de nouvelles déclarations de variables de cette manière, et vous n’avez jamais à vous soucier d’échanger un
;contre une,ou d’introduire des différences de ponctuation uniquement.
// bad
const items = getItems(),
goSportsTeam = true,
dragonball = 'z';
// bad
// (compare to above, notice the error)
const items = getItems(),
goSportsTeam = true;
dragonball = 'z';
// good
const items = getItems();
const goSportsTeam = true;
const dragonball = 'z';
- 13.3 Groupez tous vos
constet ensuite tous voslet.
Pourquoi ? Ceci est utile lorsque plus tard vous devrez peut-être assigner une variable en fonction de l’une des variables précédemment assignées.
// bad
let i, len, dragonball,
items = getItems(),
goSportsTeam = true;
// bad
let i;
const items = getItems();
let dragonball;
const goSportsTeam = true;
let len;
// good
const goSportsTeam = true;
const items = getItems();
let dragonball;
let i;
let length;
- 13.4 Assignez des variables là où vous en avez besoin, mais placez-les à un endroit raisonnable.
Pourquoi ?
letetconstont une portée de bloc et non de fonction.
// bad - unnecessary function call
function checkName(hasName) {
const name = getName();
if (hasName === 'test') {
return false;
}
if (name === 'test') {
this.setName('');
return false;
}
return name;
}
// good
function checkName(hasName) {
if (hasName === 'test') {
return false;
}
const name = getName();
if (name === 'test') {
this.setName('');
return false;
}
return name;
}
Hoisting
- 14.1 Les déclarations
varsont hissées (hoisted) vers le haut de leur portée, mais leur affectation ne l’est pas. Les déclarationsconstetletbénéficient d’un nouveau concept appelé Zones Mortes Temporelles (TDZ). Il est important de savoir pourquoi typeof n’est plus sûr.
// we know this wouldn't work (assuming there
// is no notDefined global variable)
function example() {
console.log(notDefined); // => throws a ReferenceError
}
// creating a variable declaration after you
// reference the variable will work due to
// variable hoisting. Note: the assignment
// value of `true` is not hoisted.
function example() {
console.log(declaredButNotAssigned); // => undefined
var declaredButNotAssigned = true;
}
// The interpreter is hoisting the variable
// declaration to the top of the scope,
// which means our example could be rewritten as:
function example() {
let declaredButNotAssigned;
console.log(declaredButNotAssigned); // => undefined
declaredButNotAssigned = true;
}
// using const and let
function example() {
console.log(declaredButNotAssigned); // => throws a ReferenceError
console.log(typeof declaredButNotAssigned); // => throws a ReferenceError
const declaredButNotAssigned = true;
}
- 14.2 Les expressions de fonction anonymes hissent leur nom de variable, mais pas l’affectation de la fonction.
function example() {
console.log(anonymous); // => undefined
anonymous(); // => TypeError anonymous is not a function
var anonymous = function () {
console.log('anonymous function expression');
};
}
- 14.3 Les expressions de fonction nommées hissent le nom de la variable, pas le nom de la fonction ou le corps de la fonction.
function example() {
console.log(named); // => undefined
named(); // => TypeError named is not a function
superPower(); // => ReferenceError superPower is not defined
var named = function superPower() {
console.log('Flying');
};
}
// the same is true when the function name
// is the same as the variable name.
function example() {
console.log(named); // => undefined
named(); // => TypeError named is not a function
var named = function named() {
console.log('named');
}
}
- 14.4 Les déclarations de fonction hissent leur nom et le corps de la fonction.
function example() {
superPower(); // => Flying
function superPower() {
console.log('Flying');
}
}
- Pour plus d’informations, voir JavaScript Scoping & Hoisting par Ben Cherry.
Opérateurs de Comparaison et Égalité (Comparison Operators & Equality)
-
15.1 Utilisez
===et!==au lieu de==et!=. eslint :eqeqeq -
15.2 Les instructions conditionnelles comme
ifévaluent leur expression en utilisant la coercition avec la méthode abstraiteToBooleanet suivent toujours ces règles simples :
- Objects sont évalués à true
- Undefined est évalué à false
- Null est évalué à false
- Booleans sont évalués à la valeur du booléen
- Numbers sont évalués à false si +0, -0, ou NaN, sinon true
- Strings sont évalués à false si c’est une chaîne vide
'', sinon true
if ([0] && []) {
// true
// an array (even an empty one) is an object, objects will evaluate to true
}
- 15.3 Utilisez des raccourcis.
// bad
if (name !== '') {
// ...stuff...
}
// good
if (name) {
// ...stuff...
}
// bad
if (collection.length > 0) {
// ...stuff...
}
// good
if (collection.length) {
// ...stuff...
}
- 15.4 Pour plus d’informations, voir Truth Equality and JavaScript par Angus Croll.
- 15.5 Utilisez des accolades pour créer des blocs dans les clauses
caseetdefaultqui contiennent des déclarations lexicales (par exemple,let,const,function, etclass).
Pourquoi ? Les déclarations lexicales sont visibles dans tout le bloc
switchmais ne sont initialisées que lorsqu’elles sont assignées, ce qui ne se produit que lorsque soncaseest atteint. Cela provoque des problèmes lorsque plusieurs clausescasetentent de définir la même chose.
eslint rules : no-case-declarations.
// bad
switch (foo) {
case 1:
let x = 1;
break;
case 2:
const y = 2;
break;
case 3:
function f() {}
break;
default:
class C {}
}
// good
switch (foo) {
case 1: {
let x = 1;
break;
}
case 2: {
const y = 2;
break;
}
case 3: {
function f() {}
break;
}
case 4:
bar();
break;
default: {
class C {}
}
}
- 15.7 Les opérateurs ternaires ne devraient pas être imbriqués et devraient généralement être des expressions sur une seule ligne.
eslint rules : no-nested-ternary.
// bad
const foo = maybe1 > maybe2
? "bar"
: value1 > value2 ? "baz" : null;
// better
const maybeNull = value1 > value2 ? 'baz' : null;
const foo = maybe1 > maybe2
? 'bar'
: maybeNull;
// best
const maybeNull = value1 > value2 ? 'baz' : null;
const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
- 15.8 Évitez les instructions ternaires inutiles.
eslint rules : no-unneeded-ternary.
// bad
const foo = a ? a : b;
const bar = c ? true : false;
const baz = c ? false : true;
// good
const foo = a || b;
const bar = !!c;
const baz = !c;
Blocs (Blocks)
- 16.1 Utilisez des accolades avec tous les blocs multilignes.
// bad
if (test)
return false;
// good
if (test) return false;
// good
if (test) {
return false;
}
// bad
function foo() { return false; }
// good
function bar() {
return false;
}
- 16.2 Si vous utilisez des blocs multilignes avec
ifetelse, placezelsesur la même ligne que l’accolade fermante du blocif. eslint :brace-stylejscs :disallowNewlineBeforeBlockStatements
// bad
if (test) {
thing1();
thing2();
}
else {
thing3();
}
// good
if (test) {
thing1();
thing2();
} else {
thing3();
}
Instructions de Contrôle (Control Statements)
- 17.1 Si votre instruction de contrôle (
if,whileetc.) devient trop longue ou dépasse la longueur maximale de la ligne, chaque condition (groupée) peut être placée sur une nouvelle ligne. L’opérateur logique doit commencer la ligne.
Pourquoi ? Exiger des opérateurs au début de la ligne maintient les opérateurs alignés et suit un modèle similaire au chaînage de méthodes. Cela améliore également la lisibilité en rendant la logique complexe plus facile à suivre visuellement.
// bad
if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
thing1();
}
// bad
if (foo === 123 &&
bar === 'abc') {
thing1();
}
// bad
if (foo === 123
&& bar === 'abc') {
thing1();
}
// bad
if (
foo === 123 &&
bar === 'abc'
) {
thing1();
}
// good
if (
foo === 123
&& bar === 'abc'
) {
thing1();
}
// good
if (
(foo === 123 || bar === 'abc')
&& doesItLookGoodWhenItBecomesThatLong()
&& isThisReallyHappening()
) {
thing1();
}
// good
if (foo === 123 && bar === 'abc') {
thing1();
}
- 17.2 N’utilisez pas d’opérateurs de sélection à la place des instructions de contrôle.
// bad
!isRunning && startRunning();
// good
if (!isRunning) {
startRunning();
}
Commentaires (Comments)
- 18.1 Utilisez
/** ... */pour les commentaires multilignes. Incluez une description, spécifiez les types et les valeurs pour tous les 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;
}
- 18.2 Utilisez
//pour les commentaires sur une seule ligne. Placez les commentaires sur une seule ligne sur une nouvelle ligne au-dessus du sujet du commentaire. Mettez une ligne vide avant le commentaire, sauf s’il est sur la première ligne d’un bloc.
// bad
const active = true; // is current tab
// good
// is current tab
const active = true;
// bad
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
const type = this._type || 'no type';
return type;
}
// good
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
const type = this._type || 'no type';
return type;
}
// also good
function getType() {
// set the default type to 'no type'
const type = this._type || 'no type';
return type;
}
-
18.3 Préfixer vos commentaires avec
FIXMEouTODOaide les autres développeurs à comprendre rapidement si vous signalez un problème qui doit être revu ou si vous suggérez une solution qui doit être implémentée. Ceux-ci sont différents des commentaires réguliers car ils sont actionnables. Les actions sontFIXME : -- need to figure this outouTODO : -- need to implement. -
18.4 Utilisez
// FIXME :pour annoter les problèmes.
class Calculator extends Abacus {
constructor() {
super();
// FIXME: shouldn't use a global here
total = 0;
}
}
- 18.5 Utilisez
// TODO :pour annoter les solutions aux problèmes.
class Calculator extends Abacus {
constructor() {
super();
// TODO: total should be configurable by an options param
this.total = 0;
}
}
Espaces (Whitespace)
- 19.1 Utilisez des soft tabs (espaces) définis sur 2 espaces. eslint :
indentjscs :validateIndentation
// bad
function foo() {
∙∙∙∙const name;
}
// bad
function bar() {
∙const name;
}
// good
function baz() {
∙∙const name;
}
- 19.2 Placez 1 espace avant l’accolade ouvrante. eslint :
space-before-blocksjscs :requireSpaceBeforeBlockStatements
// 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',
});
- 19.3 Placez 1 espace avant la parenthèse ouvrante dans les instructions de contrôle (
if,whileetc.). Ne placez pas d’espace entre la liste d’arguments et le nom de la fonction dans les appels et les déclarations de fonction. eslint :space-after-keywords,space-before-keywordsjscs :requireSpaceAfterKeywords
// bad
if(isJedi) {
fight ();
}
// good
if (isJedi) {
fight();
}
// bad
function fight () {
console.log ('Swooosh!');
}
// good
function fight() {
console.log('Swooosh!');
}
- 19.4 Séparez les opérateurs avec des espaces. eslint :
space-infix-opsjscs :requireSpaceBeforeBinaryOperators,requireSpaceAfterBinaryOperators
// bad
const x=y+5;
// good
const x = y + 5;
- 19.5 Terminez les fichiers par un seul saut de ligne.
// bad
(function (global) {
// ...stuff...
})(this);
// bad
(function (global) {
// ...stuff...
})(this);↵
↵
// good
(function (global) {
// ...stuff...
})(this);↵
- 19.6 Utilisez l’indentation lors de longs chaînages de méthodes (plus de 2 chaînes de méthodes). Utilisez un point au début, ce qui souligne que la ligne est un appel de méthode, pas une nouvelle instruction. eslint :
newline-per-chained-callno-whitespace-before-property
// bad
$('#items').find('.selected').highlight().end().find('.open').updateCount();
// bad
$('#items').
find('.selected').
highlight().
end().
find('.open').
updateCount();
// good
$('#items')
.find('.selected')
.highlight()
.end()
.find('.open')
.updateCount();
// bad
const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
.attr('width', (radius + margin) * 2).append('svg:g')
.attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
.call(tron.led);
// good
const leds = stage.selectAll('.led')
.data(data)
.enter().append('svg:svg')
.classed('led', true)
.attr('width', (radius + margin) * 2)
.append('svg:g')
.attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
.call(tron.led);
// good
const leds = stage.selectAll('.led').data(data);
- 19.7 Laissez une ligne vide après les blocs et avant l’instruction suivante. jscs :
requirePaddingNewLinesAfterBlocks
// bad
if (foo) {
return bar;
}
return baz;
// good
if (foo) {
return bar;
}
return baz;
// bad
const obj = {
foo() {
},
bar() {
},
};
return obj;
// good
const obj = {
foo() {
},
bar() {
},
};
return obj;
// bad
const arr = [
function foo() {
},
function bar() {
},
];
return arr;
// good
const arr = [
function foo() {
},
function bar() {
},
];
return arr;
- 19.8 Ne remplissez pas vos blocs avec des lignes vides. eslint :
padded-blocksjscs :disallowPaddingNewlinesInBlocks
// bad
function bar() {
console.log(foo);
}
// also bad
if (baz) {
console.log(qux);
} else {
console.log(foo);
}
// good
function bar() {
console.log(foo);
}
// good
if (baz) {
console.log(qux);
} else {
console.log(foo);
}
- 19.9 N’ajoutez pas d’espaces à l’intérieur des parenthèses. eslint :
space-in-parensjscs :disallowSpacesInsideParentheses
// bad
function bar( foo ) {
return foo;
}
// good
function bar(foo) {
return foo;
}
// bad
if ( foo ) {
console.log(foo);
}
// good
if (foo) {
console.log(foo);
}
- 19.10 N’ajoutez pas d’espaces à l’intérieur des crochets. eslint :
array-bracket-spacingjscs :disallowSpacesInsideArrayBrackets
// bad
const foo = [ 1, 2, 3 ];
console.log(foo[ 0 ]);
// good
const foo = [1, 2, 3];
console.log(foo[0]);
- 19.11 Ajoutez des espaces à l’intérieur des accolades. eslint :
object-curly-spacingjscs : [disallowSpacesInsideObjectBrackets](http://jscs.info/rule/
// bad
const foo = {clark: 'kent'};
// good
const foo = { clark: 'kent' };
- 19.12 Évitez les lignes de plus de 100 caractères (y compris les espaces). eslint :
max-lenjscs :maximumLineLength
Pourquoi ? Cela garantit la lisibilité et la maintenabilité.
// bad
const foo = 'Whatever national crop flips the window. The cartoon reverts within the screw. Whatever wizard constrains a helpful ally. The counterpart ascends!';
// bad
$.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.'));
// good
const foo = 'Whatever national crop flips the window. The cartoon reverts within the screw. ' +
'Whatever wizard constrains a helpful ally. The counterpart ascends!';
// good
$.ajax({
method: 'POST',
url: 'https://airbnb.com/',
data: { name: 'John' },
})
.done(() => console.log('Congratulations!'))
.fail(() => console.log('You have failed this city.'));
Virgules (Commas)
- 20.1 Virgules de tête (Leading commas) : Non. eslint :
comma-stylejscs :requireCommaBeforeLineBreak
// bad
const story = [
once
, upon
, aTime
];
// good
const story = [
once,
upon,
aTime,
];
// bad
const hero = {
firstName: 'Ada'
, lastName: 'Lovelace'
, birthYear: 1815
, superPower: 'computers'
};
// good
const hero = {
firstName: 'Ada',
lastName: 'Lovelace',
birthYear: 1815,
superPower: 'computers',
};
- 20.2 Virgule finale supplémentaire (Additional trailing comma) : Oui. eslint :
comma-danglejscs :requireTrailingComma
Pourquoi ? Cela conduit à des diffs git plus propres. De plus, les transpilateurs comme Babel supprimeront la virgule finale supplémentaire dans le code transpilé, ce qui signifie que vous n’avez pas à vous soucier du problème de virgule finale dans les navigateurs existants.
// bad - git diff without trailing comma
const hero = {
firstName: 'Florence',
lastName: 'Nightingale'
+ lastName: 'Nightingale',
+ inventorOf: ['coxcomb graph', 'modern nursing']
};
// good - git diff with trailing comma
const hero = {
firstName: 'Florence',
lastName: 'Nightingale',
+ inventorOf: ['coxcomb chart', 'modern nursing'],
};
// bad
const hero = {
firstName: 'Dana',
lastName: 'Scully'
};
const heroes = [
'Batman',
'Superman'
];
// good
const hero = {
firstName: 'Dana',
lastName: 'Scully',
};
const heroes = [
'Batman',
'Superman',
];
Point-virgules (Semicolons)
- 21.1 Oui. eslint :
semijscs :requireSemicolons
// bad
(function () {
const name = 'Skywalker'
return name
})()
// good
(() => {
const name = 'Skywalker';
return name;
}());
// good (guards against the function becoming an argument when two files with IIFEs are concatenated)
;(() => {
const name = 'Skywalker';
return name;
}());
Conversion de Type et Coercition (Type Casting & Coercion)
// => this.reviewScore = 9;
// bad
const totalScore = this.reviewScore + '';
// good
const totalScore = String(this.reviewScore);
- 22.3 Nombres : Utilisez
Numberpour le casting de type etparseInttoujours avec une base pour analyser les chaînes. eslint :radix
const inputValue = '4';
// bad
const val = new Number(inputValue);
// bad
const val = +inputValue;
// bad
const val = inputValue >> 0;
// bad
const val = parseInt(inputValue);
// good
const val = Number(inputValue);
// good
const val = parseInt(inputValue, 10);
- 22.4 Si pour une raison quelconque vous faites quelque chose de fou et que
parseIntest votre goulot d’étranglement et que vous devez utiliser Bitshift pour des raisons de performance, laissez un commentaire expliquant pourquoi et ce que vous faites.
// good
/**
* parseInt was the reason my code was slow.
* Bitshifting the String to coerce it to a
* Number made it a lot faster.
*/
const val = inputValue >> 0;
- 22.5 Note : Soyez prudent lors de l’utilisation des opérations de bitshift. Les nombres sont représentés comme des valeurs 64 bits, mais les opérations de bitshift renvoient toujours un entier 32 bits (source). Le bitshift peut entraîner un comportement inattendu pour les valeurs entières supérieures à 32 bits. Discussion. Le plus grand entier signé de 32 bits est 2,147,483,647 :
2147483647 >> 0 //=> 2147483647
2147483648 >> 0 //=> -2147483648
2147483649 >> 0 //=> -2147483647
- 22.6 Booléens :
const age = 0;
// bad
const hasAge = new Boolean(age);
// good
const hasAge = Boolean(age);
// good
const hasAge = !!age;
Conventions de Nommage (Naming Conventions)
- 23.1 Évitez les noms d’une seule lettre. Soyez descriptif avec votre nommage.
// bad
function q() {
// ...stuff...
}
// good
function query() {
// ..stuff..
}
- 23.2 Utilisez le camelCase lors du nommage des objets, fonctions et instances. eslint :
camelcasejscs :requireCamelCaseOrUpperCaseIdentifiers
// bad
const OBJEcttsssss = {};
const this_is_my_object = {};
function c() {}
// good
const thisIsMyObject = {};
function thisIsMyFunction() {}
- 23.3 Utilisez le PascalCase uniquement lors du nommage des constructeurs ou des classes. eslint :
new-capjscs :requireCapitalizedConstructors
// bad
function user(options) {
this.name = options.name;
}
const bad = new user({
name: 'nope',
});
// good
class User {
constructor(options) {
this.name = options.name;
}
}
const good = new User({
name: 'yup',
});
- 23.4 Utilisez un trait de soulignement
_au début lors du nommage des propriétés privées. eslint :no-underscore-danglejscs :disallowDanglingUnderscores
// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
// good
this._firstName = 'Panda';
- 23.5 Ne stockez pas de références à
this. Utilisez des fonctions fléchées ou Function#bind. jscs :disallowNodeTypes
// bad
function foo() {
const self = this;
return function () {
console.log(self);
};
}
// bad
function foo() {
const that = this;
return function () {
console.log(that);
};
}
// good
function foo() {
return () => {
console.log(this);
};
}
- 23.6 Si votre fichier exporte une seule classe, votre nom de fichier doit correspondre exactement au nom de votre classe.
// file contents
class CheckBox {
// ...
}
export default CheckBox;
// in some other file
// bad
import CheckBox from './checkBox';
// bad
import CheckBox from './check_box';
// good
import CheckBox from './CheckBox';
- 23.7 Utilisez le camelCase lorsque vous exportez par défaut une fonction. Votre nom de fichier doit être identique au nom de votre fonction.
function makeStyleGuide() {
}
export default makeStyleGuide;
- 23.8 Utilisez le PascalCase lorsque vous exportez un singleton / une bibliothèque de fonctions / un objet vide.
const AirbnbStyleGuide = {
es6: {
}
};
export default AirbnbStyleGuide;
Accesseurs (Accessors)
- 24.1 Les fonctions d’accès pour les propriétés ne sont pas obligatoires.
- 24.2 N’utilisez pas de getters/setters JavaScript car ils provoquent des effets de bord inattendus et sont difficiles à tester, maintenir et raisonner. Au lieu de cela, si vous créez des fonctions d’accès, utilisez getVal() et setVal(‘hello’).
// bad
dragon.age();
// good
dragon.getAge();
// bad
dragon.age(25);
// good
dragon.setAge(25);
- 24.3 Si la propriété est un booléen, utilisez
isVal()ouhasVal().
// bad
if (!dragon.age()) {
return false;
}
// good
if (!dragon.hasAge()) {
return false;
}
- 24.4 Il est acceptable de créer des fonctions get() et set(), mais soyez cohérent.
class Jedi {
constructor(options = {}) {
const lightsaber = options.lightsaber || 'blue';
this.set('lightsaber', lightsaber);
}
set(key, val) {
this[key] = val;
}
get(key) {
return this[key];
}
}
Événements (Events)
- 25.1 Lorsque vous attachez des charges utiles de données à des événements (qu’il s’agisse d’événements DOM ou quelque chose de plus propriétaire comme les événements Backbone), passez un hash au lieu d’une valeur brute. Cela permet à un contributeur ultérieur d’ajouter plus de données à la charge utile de l’événement sans trouver et mettre à jour chaque gestionnaire pour l’événement. Par exemple, au lieu de :
// bad
$(this).trigger('listingUpdated', listing.id);
...
$(this).on('listingUpdated', (e, listingId) => {
// do something with listingId
});
préférez :
// good
$(this).trigger('listingUpdated', { listingId: listing.id });
...
$(this).on('listingUpdated', (e, data) => {
// do something with data.listingId
});
jQuery
- 26.1 Préfixez les objets jQuery avec un
$. jscs :requireDollarBeforejQueryAssignment
// bad
const sidebar = $('.sidebar');
// good
const $sidebar = $('.sidebar');
// good
const $sidebarBtn = $('.sidebar-btn');
- 26.2 Mettez en cache les recherches jQuery.
// bad
function setSidebar() {
$('.sidebar').hide();
// ...stuff...
$('.sidebar').css({
'background-color': 'pink'
});
}
// good
function setSidebar() {
const $sidebar = $('.sidebar');
$sidebar.hide();
// ...stuff...
$sidebar.css({
'background-color': 'pink'
});
}
- 26.3 Pour les requêtes DOM, utilisez Cascading
$('.sidebar ul')ou parent > child$('.sidebar > ul'). jsPerf - 26.4 Utilisez
findavec des requêtes d’objet jQuery scopées.
// bad
$('ul', '.sidebar').hide();
// bad
$('.sidebar').find('ul').hide();
// good
$('.sidebar ul').hide();
// good
$('.sidebar > ul').hide();
// good
$sidebar.find('ul').hide();
Compatibilité ECMAScript 5 (ECMAScript 5 Compatibility)
- 27.1 Référez-vous à la table de compatibilité ES5 de Kangax.
Styles ECMAScript 6 (ECMAScript 6 Styles)
- 28.1 Ceci est une collection de liens vers les différentes fonctionnalités de ES6.
- Arrow Functions
- Classes
- Object Shorthand
- Object Concise
- Computed Object Properties
- Template Strings
- Destructuring
- Default Parameters
- Rest
- Array Spreads
- Let and Const
- Iterators and Generators
- Modules
Bibliothèque Standard (Standard Library)
La Bibliothèque Standard contient des utilitaires qui sont cassés mais conservés pour des raisons d’héritage.
- 29.1 Utilisez
Number.isNaNau lieu deisNaN.
Pourquoi ?
isNaNcontraint les valeurs non numériques en nombres, retournant true pour tout ce qui se convertit en NaN. Si ce comportement est souhaité, rendez-le explicite.
// bad
isNaN('1.2'); // false
isNaN('1.2.3'); // true
// good
Number.isNaN('1.2.3'); // false
Number.isNaN(Number('1.2.3')); // true
- 29.2 Utilisez
Number.isFiniteau lieu deisFinite.
Pourquoi ?
isFinitecontraint les valeurs non numériques en nombres, retournant true pour tout ce qui se convertit en un nombre fini. Si ce comportement est souhaité, rendez-le explicite.
// bad
isFinite('2e3'); // true
// good
Number.isFinite('2e3'); // false
Number.isFinite(parseInt('2e3', 10)); // true
Tests (Testing)
- 30.1 Oui.
function foo() {
return true;
}
- 30.2 Non, sérieusement :
- Peu importe le framework de test que vous utilisez, vous devriez écrire des tests !
- Essayez d’écrire beaucoup de petites fonctions pures et minimisez les endroits où les mutations se produisent.
- Soyez prudent avec les stubs et les mocks - ils peuvent rendre vos tests plus fragiles.
- Nous utilisons principalement
mochachez Airbnb.tapeest aussi utilisé occasionnellement pour de petits modules séparés. - 100% de couverture de test est un bon objectif à viser, même s’il n’est pas toujours pratique à atteindre.
- Chaque fois que vous corrigez un bug, écrivez un test de régression. Un bug corrigé sans test de régression se cassera presque certainement à nouveau à l’avenir.
Performance
- On Layout & Web Performance
- String vs Array Concat
- Try/Catch Cost In a Loop
- Bang Function
- jQuery Find vs Context, Selector
- innerHTML vs textContent for script text
- Long String Concatenation
- Loading…
Ressources (Resources)
Apprenez ES6
- Draft ECMA 2015 (ES6) Spec
- ExploringJS
- ES6 Compatibility Table
- Comprehensive Overview of ES6 Features
Lecture Obligatoire
Outils
- Code Style Linters
Autres Guides de Style
- Google JavaScript Style Guide
- jQuery Core Style Guidelines
- Principles of Writing Consistent, Idiomatic JavaScript
Autres Styles
- Naming this in nested functions - Christian Johansen
- Conditional Callbacks - Ross Allen
- Popular JavaScript Coding Conventions on Github - JeongHoon Byun
- Multiple var statements in JavaScript, not superfluous - Ben Alman
Lecture Complémentaire
- Understanding JavaScript Closures - Angus Croll
- Basic JavaScript for the impatient programmer - Dr. Axel Rauschmayer
- You Might Not Need jQuery - Zack Bloom & Adam Schwartz
- ES6 Features - Luke Hoban
- Frontend Guidelines - Benjamin De Cock
Livres
- JavaScript: The Good Parts - Douglas Crockford
- JavaScript Patterns - Stoyan Stefanov
- Pro JavaScript Design Patterns - Ross Harmes and Dustin Diaz
- High Performance Web Sites: Essential Knowledge for Front-End Engineers - Steve Souders
- Maintainable JavaScript - Nicholas C. Zakas
- JavaScript Web Applications - Alex MacCaw
- Pro JavaScript Techniques - John Resig
- Smashing Node.js: JavaScript Everywhere - Guillermo Rauch
- Secrets of the JavaScript Ninja - John Resig and Bear Bibeault
- Human JavaScript - Henrik Joreteg
- Superhero.js - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy
- JSBooks - Julien Bouquillon
- Third Party JavaScript - Ben Vinegar and Anton Kovalyov
- Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript - David Herman
- Eloquent JavaScript - Marijn Haverbeke
- You Don’t Know JS: ES6 & Beyond - Kyle Simpson
Blogs
- DailyJS
- JavaScript Weekly
- JavaScript, JavaScript…
- Bocoup Weblog
- Adequately Good
- NCZOnline
- Perfection Kills
- Ben Alman
- Dmitry Baranovskiy
- Dustin Diaz
- nettuts
Podcasts
Dans la nature (In the Wild)
Ceci est une liste d’organisations qui utilisent ce guide de style. Envoyez-nous une pull request ou une issue, et nous vous ajouterons à la liste.
- Aan Zee: AanZee/javascript
- Adult Swim: adult-swim/javascript
- Airbnb: airbnb/javascript
- Apartmint: apartmint/javascript
- Avalara: avalara/javascript
- Avant: avantcredit/javascript
- Billabong: billabong/javascript
- Bisk: bisk/javascript
- Blendle: blendle/javascript
- Brainshark: brainshark/javascript
- ComparaOnline: comparaonline/javascript
- Compass Learning: compasslearning/javascript-style-guide
- DailyMotion: dailymotion/javascript
- Digitpaint digitpaint/javascript
- Ecosia: ecosia/javascript
- Evernote: evernote/javascript-style-guide
- Evolution Gaming: evolution-gaming/javascript
- ExactTarget: ExactTarget/javascript
- Expensify Expensify/Style-Guide
- Flexberry: Flexberry/javascript-style-guide
- Gawker Media: gawkermedia/javascript
- General Electric: GeneralElectric/javascript
- GoodData: gooddata/gdc-js-style
- Grooveshark: grooveshark/javascript
- How About We: howaboutwe/javascript
- Huballin: huballin/javascript
- HubSpot: HubSpot/javascript
- Hyper: hyperoslo/javascript-playbook
- InfoJobs: InfoJobs/JavaScript-Style-Guide
- Intent Media: intentmedia/javascript
- Jam3: Jam3/Javascript-Code-Conventions
- JeopardyBot: kesne/jeopardy-bot
- JSSolutions: JSSolutions/javascript
- Kinetica Solutions: kinetica/javascript
- Mighty Spring: mightyspring/javascript
- MinnPost: MinnPost/javascript
- MitocGroup: MitocGroup/javascript
- ModCloth: modcloth/javascript
- Money Advice Service: moneyadviceservice/javascript
- Muber: muber/javascript
- National Geographic: natgeo/javascript
- National Park Service: nationalparkservice/javascript
- Nimbl3: nimbl3/javascript
- Orion Health: orionhealth/javascript
- OutBoxSoft: OutBoxSoft/javascript
- Peerby: Peerby/javascript
- Razorfish: razorfish/javascript-style-guide
- reddit: reddit/styleguide/javascript
- React: /facebook/react/blob/master/CONTRIBUTING.md#style-guide
- REI: reidev/js-style-guide
- Ripple: ripple/javascript-style-guide
- SeekingAlpha: seekingalpha/javascript-style-guide
- Shutterfly: shutterfly/javascript
- Springload: springload/javascript
- StudentSphere: studentsphere/javascript
- Target: target/javascript
- TheLadders: TheLadders/javascript
- T4R Technology: T4R-Technology/javascript
- VoxFeed: VoxFeed/javascript-style-guide
- WeBox Studio: weboxstudio/javascript
- Weggo: Weggo/javascript
- Zillow: zillow/javascript
- ZocDoc: ZocDoc/javascript
Traduction (Translation)
Ce guide de style est également disponible dans d’autres langues :
Brazilian Portuguese: armoucar/javascript-style-guide
Bulgarian: borislavvv/javascript
Catalan: fpmweb/javascript-style-guide
Chinese (Simplified): sivan/javascript-style-guide
Chinese (Traditional): jigsawye/javascript
French: nmussy/javascript-style-guide
German: timofurrer/javascript-style-guide
Italian: sinkswim/javascript-style-guide
Japanese: mitsuruog/javacript-style-guide
Korean: tipjs/javascript-style-guide
Polish: mjurczyk/javascript
Russian: uprock/javascript
Spanish: paolocarrasco/javascript-style-guide
Vietnamese: f1remoon/javascript-style-guide
Le Guide du Guide de Style JavaScript (The JavaScript Style Guide Guide)
Discutez avec nous de JavaScript
- Retrouvez-nous sur gitter.
Contributeurs (Contributors)
Licence (License)
(The MIT License)
Copyright (c) 2014-2016 Airbnb
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Modifications (Amendments)
Nous vous encourageons à forker ce guide et à modifier les règles pour qu’elles correspondent au guide de style de votre équipe. Ci-dessous, vous pouvez lister quelques modifications apportées au guide de style. Cela vous permet de mettre à jour périodiquement votre guide de style sans avoir à gérer les conflits de fusion (merge conflicts).