Throrinstudio Javascript Styleguide
Table of Content
- Table of Content
- Installation
- Utilisation
- Types
- References
- Objects
- Arrays
- Destructuring
- Strings
- Functions
- Arrow Functions
- Classes et Constructeurs
- Modules (uniquement pour projets Front pour le moment)
- Iterators et Generators
- Promesses
- Properties
- variables
- Hoisting
- Comparison Operators & Equality
- Blocks
- Commentaires
- Whitespaces
- Virgules
- Points-virgules
- Type Casting & Coercion
- Convention de nommage
- Accessors
- Events
- jQuery
- VueJS
- Performance
- Resources
Installation
Backend
npm install -DE eslint eslint-config-throrinstudio
# or
yarn add -D eslint eslint-config-throrinstudio
Utilisation
Plusieurs choix s'ouvrent à vous en fonction du type de projet utilisé. Vous devrez, pour chacun créer le fichier .eslintrc.*
de la façon suivante :
-
Projets Node.JS :
module.exports = { extends: ["eslint:recommended", "throrinstudio"], };
-
Projets VueJS 2.0 (si build avec webpack et babel) :
module.exports = { extends: [ "eslint:recommended", "plugin:vue/recommended", // à appeler en dernier pour bien prendre les surcharges du plugin vue "throrinstudio/vue", ], };
Remarque : Pour chacune de ces extensions, les règles sont identiques. Il s'agit juste des différents plugins supplémentaires qui sont ou non rajoutés. Ne vous en faites pas, ce module les installe pour vous.
Types
-
Primitives : Quand vous accédez à un type primitif, vous modifiez directement la variable.
string
number
boolean
null
undefined
const foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
-
Complexe : Quand vous accédez à un type complexe, vous travaillez directement sur la référence.
object
array
function
const foo = [1, 2]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
References
-
Utilisez
const
pour toutes vos références. N'utilisez pasvar
. eslint:prefer-const
,no-const-assign
Cela permet de ne pas réassigner vos références par mégarde et ainsi éviter des bugs tout en améliorant la compréhension de votre code.
// bad var a = 1; var b = 2; // good const a = 1; const b = 2;
-
Si vous comptez réassigner une référence, utilisez
let
à la place devar
. eslint:no-var
let
est "block-scoped" alors quevar
est "function-scopped"// bad var count = 1; if (true) { count += 1; } // good, use the let. let count = 1; if (true) { count += 1; }
-
Important :
let
etconst
sont "block-scopped" :// const and let only exist in the blocks they are defined in. { let a = 1; const b = 1; } console.log(a); // ReferenceError console.log(b); // ReferenceError
Objects
-
Utilisez la syntaxe littérale pour la créatopn des objets. eslint:
no-new-object
// bad const item = new Object(); // good const item = {};
-
Utilisez les "computed property names" quand vous créez un objet avec des propriétés dynamiques.
Ceci permet de définir votre objet en une seule fois
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, };
-
Utilisez les méthodes d'objet raccourcies. 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; }, };
-
Utilisez les valeurs raccourcies. eslint:
object-shorthand
C'est plus court à écrire et suffit amplement à la compréhension du code.
const lukeSkywalker = "Luke Skywalker"; // bad const obj = { lukeSkywalker: lukeSkywalker, }; // good const obj = { lukeSkywalker, };
-
Groupes toutes vos propriétés raccourcies à la fin de votre objet :
Cela permet de savoir facilement quelles propriétés sont des propriétés raccourcies.
const anakinSkywalker = "Anakin Skywalker"; const lukeSkywalker = "Luke Skywalker"; // bad const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, lukeSkywalker, episodeThree: 3, mayTheFourth: 4, anakinSkywalker, }; // good const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, episodeThree: 3, mayTheFourth: 4, lukeSkywalker, anakinSkywalker, };
-
Utilisez uniquement les quotes sur les noms de fields si leur nom est invalide sans. eslint:
quote-props
En général, on considère ceci simplement plus facile à lire. Ça améliore le syntax highlighting, et c'est surtout plus optimisé par plusieurs moteurs JS.
// bad const bad = { foo: 3, bar: 4, "data-blah": 5, }; // good const good = { foo: 3, bar: 4, "data-blah": 5, };
-
Préférez l'opérateur spread au lieu de
Object.assign
pour copier des objets. Utilisez l'opérateur rest pour récupérer un nouvel objet en omettant certaines propriétés.// 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 }
Arrays
-
Utilisez la syntaxe littérale pour la créatopn des arrays. eslint:
no-array-constructor
// bad const items = new Array(); // good const items = [];
-
Utilisez Array#push plutôt que d'ajouter directement une valeur à votre tableau.
const someStack = []; // bad someStack[someStack.length] = "abracadabra"; // good someStack.push("abracadabra");
-
Utilisez le spread operator
...
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];
-
Pour convertir un array-like objet en array, utilisez Array.from.
const foo = document.querySelectorAll(".foo"); const nodes = Array.from(foo);
-
Utilisez un return statement dans les callbacks des méthodes d'array. Il est possible de ne pas le mettre si le contenu de la fonction peut se faire en un seul traitement. 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] = flatten; }); // 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; });
Destructuring
-
Utilisez les objects destructuring si vous voulez accéder et utiliser plusieures propriétés d'un objet.
Le destructuring vous permet de ne pas créer des références 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}`; }
-
Utilisez les array destructuring
const arr = [1, 2, 3, 4]; // bad const first = arr[0]; const second = arr[1]; // good const [first, second] = arr;
-
Utilisez l'object destructuring pour retourner plusieures valeurs, pas l'array destructuring.
Vous pouvez ajouter de nouvelles propriétés ou changer l'ordre des éléments sans casser les différents appels.
// 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);
Strings
-
Utilisez les simples quotes
''
pour les strings. eslint:quotes
// bad const name = "Capt. Janeway"; // bad - template literals should contain interpolation or newlines const name = `Capt. Janeway`; // good const name = "Capt. Janeway";
-
Les Strings qui font que la ligne dépasse les 100 caractères ne dois plus être écrite sur plusieurs lignes utilisant les concaténations.
Les strings cassés en plusieurs parties compliquent les recherches et le travail avec.
// 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.";
-
Lors de la création de strings utilisant des variables, utilisez les templates de Strings 9ES6) au lieu de la concaténation. eslint:
prefer-template
template-curly-spacing
Les templates vous permettent d'avoir des strings lisibles facilement, une syntaxe propre avec de vrais sauts de ligne quand vous en voulez ainsi que la feature d'interpolations de variables.
// 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}?`; }
-
Ne jamais utiliser la commande
eval()
. eslint no-eval -
Ne pas nécessairement échapper des caractères dans les Strings. eslint:
no-useless-escape
Les Backslashes compliquent la lecture. Ils ne doivent uniquement être présents par nécessité.
// bad const foo = "'this' is \"quoted\""; // good const foo = "'this' is \"quoted\""; const foo = `my name is '${name}'`;
Functions
-
Utilisez les expressions de fonctions au lieux des déclarations de fonction. eslint:
func-style
Les déclarations de fonctions sont hissées (déclarées en premier, avant n'importe quelle variable, ...). Il est donc facile - trop facile - de référencer cette fonction avant de la définir dans le fichier. Ceci complique fortement la lecture et la maintenabilité du code. N'oubliez surtout pas de nommer vos fonctions. Des fonctions anonymes compliquent le debug avec le résultat d'une callstack d'erreur. Si votre fonction devient trop compliquée et trop "grosse", vous devez peut-être la sortir de votre fichier actuel pour en faire un module à part entière.
// bad function foo() { // ... } // bad const foo = function () { // ... }; // good const foo = function bar() { // ... };
-
Wrappez les fonctions appelées immédiatement entre parenthèses. eslint:
wrap-iife
Une expression de fonction immédiatement appelée est une unité unique - l'enveloppant à la fois elle et ses parenthèses d'invocation, entre parenthèses, l'exprime clairement. Notez que dans un monde avec des modules partout, vous n'avez presque jamais besoin d'un IIFE.
// immediately-invoked function expression (IIFE) (function () { console.log("Welcome to the Internet. Please follow me."); })();
-
Ne jamais déclarer une fonction dans un block non fonctionnel (if, while, ...). Assignez votre fonction à une variable à la place. eslint:
no-loop-func
-
Note : ECMA-262 définit un "block" comme une liste de différents statements. Une déclaration de fonction n'est en aucun cas un statement. Read ECMA-262's note on this issue.
// bad if (currentUser) { function test() { console.log("Nope."); } } // good let test; if (currentUser) { test = () => { console.log("Yup."); }; }
-
Ne jamais appeler un paramètre de fonctions
arguments
. Ceci peut ammener des confusions ou des problèmes avec l'objetarguments
disponible dans le scope de chaque fonction.// bad function foo(name, options, arguments) { // ... } // good function foo(name, options, args) { // ... }
-
Au lieu d'utiliser l'objet
arguments
, il est mieux et plus simple de passer par l'opérateur...
. eslint:prefer-rest-params
...
est beaucoup plus explicite pour les arguments que vous pouvez rajouter dans une fonction. De plus les arguments récupérés avec forment un véritable Array.// bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(""); } // good function concatenateAll(...args) { return args.join(""); }
-
Utilisez les paramètres par défaut plutôt que de faire du mutating.
// really bad function handleThings(opts) { // No! We shouldn't mutate function arguments. // Double bad: if opts is falsy it'll be set to an object which may // be what you want but it can introduce subtle bugs. opts = opts || {}; // ... } // still bad function handleThings(opts) { if (opts === void 0) { opts = {}; } // ... } // good function handleThings(opts = {}) { // ... }
-
Évitez les effets de bord avec les paramètres par défaut
var b = 1; // bad function count(a = b++) { console.log(a); } count(); // 1 count(); // 2 count(3); // 3 count(); // 3
-
Toujours mettre les paramêtres par défaut en dernier
// bad function handleThings(opts = {}, name) { // ... } // good function handleThings(name, opts = {}) { // ... }
-
Ne jamais utiliser le constructeur
Function
pour créer une nouvelle fonction. eslint:no-new-func
Créer une fonction par cette méthode évalue la String de ma même manière que le
eval()
.// bad var add = new Function("a", "b", "return a + b"); // still bad var subtract = Function("a", "b", "return a - b");
-
Espacement dans les signatures de fonction. eslint:
space-before-function-paren
space-before-blocks
La cohérence est bonne, et vous ne devriez pas avoir à ajouter ou supprimer un espace lors de l'ajout ou la suppression d'un nom.
// bad const f = function () {}; const g = function () {}; const h = function () {}; // good const x = function () {}; const y = function a() {};
-
Ne jamais surcharger des paramètres. Remarque : Cette limitation est désactivée pour les fonctions
map
,filter
, et autres Promesses.Réassigner des paramètres peut causer des effets de bord avec la stack appelante.
// bad function f1(obj) { obj.key = 1; } // good function f2(obj) { const key = Object.prototype.hasOwnProperty.call(obj, "key") ? obj.key : 1; }
-
Ne jamais réassigner des paramètres.
Réassigner des paramètres peut causer des effets de bord surtout si vous accédez à l'objet
arguments
. Cela peut aussi causer des soucis d'optimisation. Surtout en V8.// 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) { // ... }
-
Préférez l'utilisation du spread operator
...
pour appeler des fonctions avec un nombre de paramètres variables. eslint:prefer-spread
C'est plus propre, vous n'avez pas à spécifier le contexte et vous n'avez pas à coupler un
new
avecapply
.// bad const x = [1, 2, 3, 4, 5]; console.log.apply(console, x); // good const x = [1, 2, 3, 4, 5]; console.log(...x); // bad new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]))(); // good new Date(...[2016, 8, 5]);
-
Les fonctions avec des signatures, ou invications, sur plusieurs lignes doivent êtres indentées comme toute autre liste dans ce guide : Avec chaque item sur une nouvelle ligne et une
,
en fin de ligne, y compris sur la dernière.// bad function foo(bar, baz, quux) { // ... } // good function foo(bar, baz, quux) { // ... } // bad console.log(foo, bar, baz); // good console.log(foo, bar, baz);
-
Il est interdit d'avoir du code après des
return
,throw
,continue
, etbreak
. eslint :no-unreachable
// bad function foo() { return true; console.log("done"); } function bar() { throw new Error("Oops!"); console.log("done"); } while (value) { break; console.log("done"); } throw new Error("Oops!"); console.log("done"); function baz() { if (Math.random() < 0.5) { return; } else { throw new Error(); } console.log("done"); } for (;;) {} console.log("done"); // good function foo() { return bar(); function bar() { return 1; } } function bar() { return x; var x; } switch (foo) { case 1: break; var x; }
Arrow Functions
-
Quand vous devez passer par une expression de fonctions (quand vous passez une fonction anonyme), utilisez la notation de fonctions fléchées. eslint:
prefer-arrow-callback
,arrow-spacing
Ça créer une version de la fonction utilisée dans le contexte
this
, qui est la plupart du temps ce que vous voulez (évite unbind(this)
)// 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; });
-
Si le contenu de la fonction fléchée se résume à une seule expression, oubliez les accolades et utilisez le
return
implicite. Sinon, laissez les et utilisez unreturn
statement. eslint:arrow-parens
,arrow-body-style
Sucre syntaxique. Il y a une meilleure lecture quand plusieurs fonctions sont enchaînées ensemble.
// 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}.`; }); // good [1, 2, 3].map((number, index) => ({ [index]: number, }));
-
Dans le cas où l'expression s'étend sur plusieurs lignes, l'envelopper entre parenthèses pour une meilleure lisibilité.
Elles indiquent clairement où commence et se termine la fonction.
// bad ["get", "post", "put"].map((httpMethod) => Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod ) ); // good ["get", "post", "put"].map((httpMethod) => Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod ) );
-
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 pour plus de clarté et de cohérence. Remarque: il est également acceptable de toujours utiliser des parenthèses. Dans ce cas, utilisez l'option "always" option pour eslint. eslint:
arrow-parens
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 don’t want it to take up space on the .map line!` ); // 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; });
-
É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) => item.height > 256 ? item.largeSize : item.smallSize; // good const itemHeight = (item) => { const { height, largeSize, smallSize } = item; return height > 256 ? largeSize : smallSize; };
Classes et Constructeurs
-
Toujours utiliser
class
. Évitez de manipulerprototype
directement.La syntaxe
class
est 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; } }
-
Utilisez
extends
pour les héritagesIl s'agit d'un moyen intégré d'hériter des fonctionnalités de 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]; } }
-
Les méthodes peuvent retourner
this
pour faciliter le chaînage des méthodes.// 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);
-
Il est normal d'écrire une méthode personnalisée toString (), il suffit de s'assurer de son bon fonctionnement et qu'elle ne provoque aucun effet secondaire.
class Jedi { constructor(options = {}) { this.name = options.name || "no name"; } getName() { return this.name; } toString() { return `Jedi - ${this.getName()}`; } }
-
Les classes ont un constructeur par défaut s'il n'est pas spécifié. Une fonction de constructeur vide ou une déléguée à une classe parente est inutile. eslint:
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"; } }
-
Évitez les doublons. eslint:
no-dupe-class-members
Lors d'une déclaration de membres de classes en double, la classe préfèrera la dernière saisie.
// bad class Foo { bar() { return 1; } bar() { return 2; } } // good class Foo { bar() { return 1; } } // good class Foo { bar() { return 2; } }
Modules (uniquement pour projets Front pour le moment)
-
Utilisez toujours des modules (
import
/export
) sur un système de modules non standard. Vous pouvez toujours transpiler vers votre système de module préféré.Les modules sont l'avenir, commençons à utiliser l'avenir maintenant. Et puis ce sont surtout les nouveaux standards ES6
// 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;
-
N'utilisez pas les wildcards import
Cela garantit une exportation par défaut.
// bad import * as AirbnbStyleGuide from "./AirbnbStyleGuide"; // good import AirbnbStyleGuide from "./AirbnbStyleGuide";
-
Et n'exportez pas directement d'un import
Bien que le one-liner soit concis, le fait d'avoir un moyen clair d'importer et un moyen clair 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;
-
Importez uniquement à partir d'un chemin/module en un seul endroit. eslint:
no-duplicate-imports
Avoir plusieurs lignes qui importent à partir du même chemin peut rendre le code plus difficile à maintenir.
// bad import foo from "foo"; // … some other imports … // import { named1, named2 } from "foo"; // good import foo, { named1, named2 } from "foo"; // good import foo, { named1, named2 } from "foo";
-
N'exportez pas de mutable bindings. eslint:
import/no-mutable-exports
// bad let foo = 3; export { foo }; // good const foo = 3; export { foo };
-
Dans un module avec un seul export, préférez utiliser le default export plutôt qu'un export nommé. eslint:
import/prefer-default-export
// bad export function foo() {} // good export default function foo() {}
-
Mettez tous vos import avant n'importe quel autre statement. eslint:
import/first
Puisque les
import
sont hissés, les garder en début de fichier empêche un comportement bizarre.// bad import foo from "foo"; foo.init(); import bar from "bar"; // good import foo from "foo"; import bar from "bar"; foo.init();
-
Interdire la syntaxe de Webpack dans les
import
. eslint:import/no-webpack-loader-syntax
Si vous utilisez la syntaxe de Webpack dans l'import, vous couplez fortement votre code à ce builder. Il est plutôt conseillé de mettre en place les différents loaders dans
webpack.config.js
.// bad import fooSass from "css!sass!foo.scss"; import barCss from "style!css!bar.css"; // good import fooSass from "foo.scss"; import barCss from "bar.css";
Iterators et Generators
-
N'utilisez pas d'itérateurs. Préférez les fonctions d'ordre supérieur de JavaScript plutôt que les boucles comme
for-in
oufor-of
. eslint:no-iterator
no-restricted-syntax
Fait respecter nos règles sur les immutables. Traiter avec des fonctions pures qui retournent des valeurs est plus facile à comprendre et permet d'éviter de possibles effets de bord.
Utiliser
map()
/every()
/filter()
/find()
/findIndex ()
/reduce()
/some()
/ ... pour itérer sur des tableaux , EtObject.keys()
/Object.values()
/Object.entries()
pour produire des tableaux afin que vous puissiez itérer sur des objets.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; // bad const increasedByOne = []; for (let i = 0; i < numbers.length; i++) { increasedByOne.push(numbers[i] + 1); } // good const increasedByOne = []; numbers.forEach((num) => increasedByOne.push(num + 1)); // best (keeping it functional) const increasedByOne = numbers.map((num) => num + 1);
-
N'utilisez pas encore les générateurs Front uniquement.
Ils ne peuvent pas être convertis en ES5.
-
Si vous devez utiliser des générateurs, ou si vous négligez nos conseils, assurez-vous que la signature de fonction est espacée correctement. eslint:
generator-star-spacing
function
et*
font partie du même mot-clé conceptuel -*
n'est pas un modificateur pourfunction
,function*
est une construction unique, différente defunction
.// bad function* foo() { // ... } // bad const bar = function* () { // ... }; // bad const baz = function* () { // ... }; // bad const quux = function* () { // ... }; // bad function* foo() { // ... } // bad function* foo() { // ... } // very bad function* foo() { // ... } // very bad const wat = function* () { // ... }; // good function* foo() { // ... } // good const foo = function* () { // ... };
Promesses
-
Ne pas d'exécuteurs
async
pour les promesses. eslintno-async-promise-executor
// bad const result = new Promise(async (resolve, reject) => { readFile("foo.txt", function (err, result) { if (err) { reject(err); } else { resolve(result); } }); }); const result = new Promise(async (resolve, reject) => { resolve(await foo); }); // good const result = new Promise((resolve, reject) => { readFile("foo.txt", function (err, result) { if (err) { reject(err); } else { resolve(result); } }); }); const result = Promise.resolve(foo);
Properties
-
Utiliser la notation par points pour accéder aux propriétés. eslint:
dot-notation
const luke = { jedi: true, age: 28, }; // bad const isJedi = luke["jedi"]; // good const isJedi = luke.jedi;
-
Utilisez la notation entre crochets
[]
pour accéder aux propriétés avec une variable.const luke = { jedi: true, age: 28, }; function getProp(prop) { return luke[prop]; } const isJedi = getProp("jedi");
Variables
-
Toujours utiliser
const
pour déclarer les variables. Si vous ne le faites pas, vous obtiendrez des variables globales. eslint:no-undef
prefer-const
// bad superPower = new SuperPower(); // good const superPower = new SuperPower();
-
Utilisez une déclaration
const
par variable. eslint:one-var
Il est plus facile d'ajouter de nouvelles déclarations de variables de cette façon et vous ne devez jamais vous préoccuper d'échanger un
;
pour un,
ou d'introduire des différences de ponctuation. Vous pouvez également parcourir chaque déclaration avec le débogueur, au lieu de sauter à travers tous les à la fois.// bad const items = getItems(), goSportsTeam = true, dragonball = "z"; // bad // (compare to above, and try to spot the mistake) const items = getItems(), goSportsTeam = true; dragonball = "z"; // good const items = getItems(); const goSportsTeam = true; const dragonball = "z";
-
Groupez tous vos
const
et groupes tous voslet
.C'est utile lorsque plus tard vous devrez peut-être affecter une variable en fonction de l'une des variables assignées précédemment.
// 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;
-
Attribuez des variables là où vous en avez besoin, mais placez-les dans un endroit raisonnable.
-
let
etconst
sont des variables de block. Vous devrez les définir en fonction du block pouvant les utiliser.
// 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; }
-
-
Ne chaînez pas les assignements de variable.
Chaîner des assignements de variables créer des variables globales.
// bad (function example() { // JavaScript interprets this as // let a = ( b = ( c = 1 ) ); // The let keyword only applies to variable a; variables b and c become // global variables. let a = (b = c = 1); })(); console.log(a); // undefined console.log(b); // 1 console.log(c); // 1 // good (function example() { let a = 1; let b = a; let c = a; })(); console.log(a); // undefined console.log(b); // undefined console.log(c); // undefined // the same applies for `const`
Hoisting
-
la déclaration des
var
se trouve hissée au plus haut de son scope. Leur assignement non. les déclarations deconst
etlet
utilisent un nouveau concept appelé Temporal Dead Zones (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; }
-
Les expressions de fonction anonymes hissent leur nom de variable, mais pas l'assignement de fonction.
function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function () { console.log("anonymous function expression"); }; }
-
Les expressions de fonction nommées hisser 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"); }; }
-
Les déclarations de fonctions hissent leur nom et le corps de la fonction.
function example() { superPower(); // => Flying function superPower() { console.log("Flying"); } }
-
Pour plus d'informations, vous pouvez vous référer à JavaScript Scoping & Hoisting par Ben Cherry.
Comparison Operators & Equality
-
Utilisez
===
et!==
plutôt que==
et!=
. eslint:eqeqeq
-
Les instructions conditionnelles telles que l'instruction
if
évaluent l'expression en utilisant la coercition avec la méthode abstraiteToBoolean
et suivent toujours ces règles simples:- Objects évalué en true
- Undefined évalué en false
- Null évalué en false
- Booleans évalué en valeur du boolean
- Numbers évalué en false si +0, -0, or NaN, sinon true
-
Strings évalué en false si string vide
''
, sinon true
if ([0] && []) { // true // an array (even an empty one) is an object, objects will evaluate to true }
-
Utilisez des raccourcis pour les booléens, mais des comparaisons explicites pour les chaînes et les nombres.
// bad if (isValid === true) { // ... } // good if (isValid) { // ... } // bad if (name) { // ... } // good if (name !== "") { // ... } // bad if (collection.length) { // ... } // good if (collection.length > 0) { // ... }
-
Pour plus d'informations, regardez Truth Equality and JavaScript par Angus Croll.
-
Utilisez des accolades pour créer des blocs dans les clauses
case
etdefault
qui contiennent des déclarations lexicales (par exemple,let
,const
,function
etclass
). eslint:no-case-declarations
.Les déclarations lexicales sont visibles dans tout le bloc
switch
mais ne sont initialisées que lorsqu'elles sont affectées, ce qui ne se produit que lorsque soncase
est atteint. Cela provoque des problèmes lorsque plusieurs clausescase
tentent de définir la même chose.// 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 {} } }
-
Les ternaires ne doivent pas être imbriqués et sont généralement des expressions à une seule ligne. eslint:
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;
-
Évitez les déclarations ternaires inutiles. eslint:
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;
Blocks
-
Utilisez les accolades pour tous les blocks 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; }
-
Si vous utilisez des blocs multi-lignes avec
if
etelse
, placezelse
sur la même ligne que l'attache de fermeture de votre blocif
. eslint:brace-style
// bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
-
Ne réassignez pas de variables dans les blocks conditionnels. eslint :
no-cond-assign
// bad let x; if ((x = 0)) { let b = 1; } // Practical example that is similar to an error function setHeight(someNode) { "use strict"; do { someNode.height = "100px"; } while ((someNode = someNode.parentNode)); }
Commentaires
-
Utilisez
/** ... */
pour les commentaires multilignes.// bad // make() returns a new element // based on the passed in tag name // // @param {String} tag // @return {Element} element function make(tag) { // ... return element; } // good /** * make() returns a new element * based on the passed-in tag name */ function make(tag) { // ... return element; }
-
Utilisez
//
pour les commentaires d'une seule ligne. Placez les commentaires d'une ligne sur une nouvelle ligne au-dessus du sujet du commentaire. Mettez une ligne vide avant le commentaire 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; }
-
Commencez tous les commentaires avec un espace pour faciliter la lecture. eslint:
spaced-comment
// bad //is current tab const active = true; // good // is current tab const active = true; // bad /** *make() returns a new element *based on the passed-in tag name */ function make(tag) { // ... return element; } // good /** * make() returns a new element * based on the passed-in tag name */ function make(tag) { // ... return element; }
-
Préfixer vos commentaires avec
FIXME
ouTODO
peut aider d'autres développeurs à comprendre rapidement si vous signalez un problème qui doit être revu, ou si vous proposez une solution au problème qui doit être mis en œuvre. Ceux-ci sont différents des commentaires réguliers parce qu'ils sont susceptibles d'indiquer une action à effectuer. Les actions sontFIXME: - besoin de comprendre cela
ouTODO: - besoin d'implémenter
. -
Utilisez
// FIXME:
pour noter un problèmeclass Calculator extends Abacus { constructor() { super(); // FIXME: shouldn't use a global here total = 0; } }
-
Utilisez
// TODO:
pour indiquer une action à faire ou pour donner une solution à un problème.class Calculator extends Abacus { constructor() { super(); // TODO: total should be configurable by an options param this.total = 0; } }
Whitespaces
-
Utilisez l'indentation légère (caractère espace) composé de 4 espaces. eslint:
indent
// bad function foo() { ∙∙let name; } // bad function bar() { ∙let name; } // good function baz() { ∙∙∙∙let name; }
-
Placez 1 espace avant l'accolade de tête. eslint:
space-before-blocks
// 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", });
-
Placez 1 espace avant la parenthèse ouvrante dans les instructions de contrôle (
if
,while
, etc.). Ne placez aucun espace entre la liste des arguments et le nom de la fonction dans les appels de fonction et les déclarations. eslint:keyword-spacing
// bad if (isJedi) { fight(); } // good if (isJedi) { fight(); } // bad function fight() { console.log("Swooosh!"); } // good function fight() { console.log("Swooosh!"); }
-
Séparer les opérateurs avec des espaces. eslint:
space-infix-ops
// bad const x = y + 5; // good const x = y + 5;
-
Terminez vos fichiers par une ligne vide. eslint:
eol-last
// bad import { es6 } from "./AirbnbStyleGuide"; // ... export default es6;
// bad import { es6 } from './AirbnbStyleGuide'; // ... export default es6;↵ ↵
// good import { es6 } from './AirbnbStyleGuide'; // ... export default es6;↵
-
Utilisez l'indentation lors de la création de longues chaînes de méthodes (plus de 2 chaînes de méthodes). Utilisez un point de tête, qui souligne que la ligne est un appel de méthode, pas une nouvelle instruction. eslint:
newline-per-chained-call
no-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);
-
Laissez une ligne blanche après un block et le statement qui suit.
// 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;
-
Ne commencez et/ou ne finissez pas vos blocks par une ligne vide. eslint:
padded-blocks
// 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); }
-
Ne mettez pas d'espace dans les parenthèses. eslint:
space-in-parens
// bad function bar(foo) { return foo; } // good function bar(foo) { return foo; } // bad if (foo) { console.log(foo); } // good if (foo) { console.log(foo); }
-
Ne pas mettre d'espaces entre crochets. eslint:
array-bracket-spacing
// bad const foo = [1, 2, 3]; console.log(foo[0]); // good const foo = [1, 2, 3]; console.log(foo[0]);
-
Ajoutez des espaces dans des accolades. eslint:
object-curly-spacing
// bad const foo = { clark: "kent" }; // good const foo = { clark: "kent" };
-
Évitez d'avoir des lignes de code qui sont plus long que 125 caractères (y compris les espaces). Note: les chaînes longues sont exemptées de cette règle et ne doivent pas être rompues. eslint:
max-len
Cela garantit la lisibilité et la maintenabilité.
// bad const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy; // 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 = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy; // good $.ajax({ method: "POST", url: "https://airbnb.com/", data: { name: "John" }, }) .done(() => console.log("Congratulations!")) .fail(() => console.log("You have failed this city."));
-
Pour les objets définits sur plusieurs lignes, aligner les clés/valeurs. eslint :
key-spacing
// bad const obj = { firstname: "Joe", lastname: "Black", age: 12, }; // good const obj = { firstname: "Joe", lastname: "Black", age: 12, };
-
Ne mettez jamais d'espace lors de l'utilisation du spread/rest operator (
...
). eslint :rest-spread-spacing
// bad fn(... args) [... arr, 4, 5, 6] let [a, b, ... arr] = [1, 2, 3, 4, 5]; function fn(... args) { console.log(args); } let { x, y, ... z } = { x: 1, y: 2, a: 3, b: 4 }; let n = { x, y, ... z }; // good fn(...args) [...arr, 4, 5, 6] let [a, b, ...arr] = [1, 2, 3, 4, 5]; function fn(...args) { console.log(args); } let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; let n = { x, y, ...z };
Virgules
-
Virgules en début de ligne ? NOPE. eslint:
comma-style
// 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", };
-
Mettre une virgule en fin d'objet/array. eslint:
comma-dangle
Cela conduit à des différences de git plus simples. En outre, les transpilers comme Babel supprimeront la virgule de fin de traînée dans le code transpillé qui signifie que vous n'avez pas à vous soucier du [problème de dernière virgule] (https://github.com/airbnb/javascript/blob/es5-deprecated/es5/README.md#commas) sur les navigateurs.
// bad - git diff without trailing comma const hero = { firstName: 'Florence', - lastName: 'Nightingale' + lastName: 'Nightingale', + inventorOf: ['coxcomb chart', '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"]; // bad function createHero(firstName, lastName, inventorOf) { // does nothing } // good function createHero(firstName, lastName, inventorOf) { // does nothing } // good (note that a comma must not appear after a "rest" element) function createHero(firstName, lastName, inventorOf, ...heroArgs) { // does nothing } // bad createHero(firstName, lastName, inventorOf); // good createHero(firstName, lastName, inventorOf); // good (note that a comma must not appear after a "rest" element) createHero(firstName, lastName, inventorOf, ...heroArgs);
Points-virgules
-
Obligatoire en fin d'un statement (si elles existent c'est pour une bonne raison). eslint:
semi
// bad (function () { const name = "Skywalker"; return name; })()( // good (function () { const name = "Skywalker"; return name; })() ); // good, but legacy (guards against the function becoming an argument when two files with IIFEs are concatenated) (() => { const name = "Skywalker"; return name; })();
Type Casting & Coercion
-
Effectuer la coercition de type au début de la déclaration.
-
Strings:
// => this.reviewScore = 9; // bad const totalScore = this.reviewScore + ""; // invokes this.reviewScore.valueOf() // bad const totalScore = this.reviewScore.toString(); // isn't guaranteed to return a string // good const totalScore = String(this.reviewScore);
-
Nombres. Selon les cas, utilisez l'opérateur
+
ou bienparseInt
en précisant obligatoirement sa base de conversion. Privilégiez ce dernier le plus possible. eslint:radix
const inputValue = "4"; // bad const val = new Number(inputValue); // good const val = +inputValue; // bad const val = inputValue >> 0; // bad const val = parseInt(inputValue); // good const val = Number(inputValue); // good const val = parseInt(inputValue, 10);
-
Si pour une raison ou pour une autre, vous faites un traitement contenant un
parseInt
et que celui-ci vous ralenti fortement votre traitement, dans ce cas vous pouvez utiliser le décallage de bits. Mais uniquement pour des raisons de performance. Dans ce cas, laissez un commentaire expliquant pourquoi vous faites ça.// 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;
-
Note : Faites très attention lors de l'utilisation des décallages de bits. Les nombres sont représentés sur 64-bit. Le décallage de bits retourne toujours des nombres représentés sur 32 bits (source). Ceci peut entraîner des conversions erronées et non prévues pour les nombres plus larges que 32 bits. Discussion. Le plus grand nombre signé sur 32 bits est de 2147483647 :
2147483647 >> 0; // => 2147483647 2147483648 >> 0; // => -2147483648 2147483649 >> 0; // => -2147483647
-
Booléens :
const age = 0; // bad const hasAge = new Boolean(age); // good const hasAge = Boolean(age); // best const hasAge = !!age;
Convention de nommage
-
Évitez les noms composés d'une seule lettre. Soyez descriptif avec votre nom. eslint:
id-length
// bad function q() { // ... } // good function query() { // ... }
-
Utilisez le camelCase quand vous nommez des objets, functions et instances. eslint:
camelcase
// bad const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} // good const thisIsMyObject = {}; function thisIsMyFunction() {}
-
Utilisez le PascalCase uniquement pour nommer vos constructeurs et classes. eslint:
new-cap
// 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", });
-
N'utilisez pas les traits d'union et les underscore. eslint:
no-underscore-dangle
JavaScript n'a pas le concept de choses privées en termes de propriétés ou de méthodes. Bien qu'un underscore en début de nom est une convention commune pour signifier "privé", en fait, ces propriétés sont pleinement publiques, et comme tel, font partie de votre API public. Cette convention pourrait conduire les développeurs à penser à tort qu'une modification ne sera pas considérée comme rupture, ou que des tests ne sont pas nécessaires. Tl; dr: si vous voulez que quelque chose soit «privé», il ne doit pas être présent.
// bad this.__firstName__ = "Panda"; this.firstName_ = "Panda"; this._firstName = "Panda"; // good this.firstName = "Panda";
-
Ne sauvegardez pas la référence de
this
. Utilisez les fonctions fléchées ou bien Function#bind.// 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); }; }
-
Le nom du fichier doit correspondre au nom de la variable pour son export par défaut.
// file 1 contents class CheckBox { // ... } export default CheckBox; // file 2 contents export default function fortyTwo() { return 42; } // file 3 contents export default function insideDirectory() {} // in some other file // bad import CheckBox from './checkBox'; // PascalCase import/export, camelCase filename import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export // bad import CheckBox from './check_box'; // PascalCase import/export, snake_case filename import forty_two from './forty_two'; // snake_case import/filename, camelCase export import inside_directory from './inside_directory'; // snake_case import, camelCase export import index from './inside_directory/index'; // requiring the index file explicitly import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly // good import CheckBox from './CheckBox'; // PascalCase export/import/filename import fortyTwo from './fortyTwo'; // camelCase export/import/filename import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index" // ^ supports both insideDirectory.js and insideDirectory/index.js
-
Utilisez le camelCase quand le
export default
est pour une fonction. Votre fichier nom de fichier doit être identique à votre fonctionfunction makeStyleGuide() { // ... } export default makeStyleGuide;
-
Utilisez le PascalCase quand le
export default
est pour un constructor / classes / singleton / constanteconst AirbnbStyleGuide = { es6: {}, }; export default AirbnbStyleGuide;
-
Les acronymes et les initialismes doivent toujours être en majuscules ou entièrement en minuscules.
// bad import SmsContainer from "./containers/SmsContainer"; // bad const HttpRequests = [ // ... ]; // good import SMSContainer from "./containers/SMSContainer"; // good const HTTPRequests = [ // ... ]; // best import TextMessageContainer from "./containers/TextMessageContainer"; // best const Requests = [ // ... ];
Accessors
-
Les fonctions d'accesseur pour les propriétés ne sont pas requises.
-
N'utilisez pas les getters / setters JavaScript car ils provoquent des effets secondaires inattendus et sont plus difficiles à tester, à maintenir et à raisonner. Au lieu de cela, si vous faites des fonctions d'accesseur, utilisez
getVal()
etsetVal('bonjour')
.// bad class Dragon { get age() { // ... } set age(value) { // ... } } // good class Dragon { getAge() { // ... } setAge(value) { // ... } }
-
Si la propriété est un booléen, utilisez
isVal()
ouhasVal()
// bad if (!dragon.dead()) { return false; } // good if (!dragon.isDead()) { return false; }
-
Vous pouvez très bien utiliser les fonctions
get()
etset()
mais soyez cohérents.class Jedi { constructor(options = {}) { const lightsaber = options.lightsaber || "blue"; this.set("lightsaber", lightsaber); } set(key, val) { this[key] = val; } get(key) { return this[key]; } }
Events
-
Quand vous attachez des paramètres à des événements (événements VueJS, ReactJS ou NodeJS), passez par un objet plutôt que par la valeur brute. Cela permet d'ajouter plus facilement d'autres paramètres à cette fonction sans devoir tout reprendre. Par exemple, au lieux de faire :
this.emit("listingUpdated", listing.id); // ... this.on("listingUpdated", (listingId) => { // do something with listingId });
préférez :
this.emit("listingUpdated", { listingId: listing.id, }); // ... this.on("listingUpdated", (data) => { // do something with listingId });
jQuery
- Ne plus jamais utiliser jQuery dans vos projets ni de library externes l'utilisant. Pour le front, les nouveaux frameworks font le job sans nécessairement inclure jQuery. De plus, lors de la compilation, vous risquez d'avoir des library qui ont jQuery dans différentes versions et cela peut entraîner des erreurs d'exécution car la compilation retournera différentes occurences de jQuery.
VueJS
-
Utilisation des règles de
plugin:vue/recommended
: Voir les règles mais avec des changements minimes : -
Surcharge de la rules
vue/html-indent
. L'espacement dans le tagtemplate
est de 4 espaces :// bad <template> <div class="item"> <span>Contenu du span</span> </div> </template> // good <template> <div class="item"> <span>Contenu du span</span> </div> </template>
-
Surcharge de la rule
vue/component-name-in-template-casing
. Les composants dans le HTML appelés autrement qu'en kebabCase sont retournés en erreur.<template> <!-- ✓ GOOD --> <the-component /> <!-- ✗ BAD --> <TheComponent /> <theComponent /> <Thecomponent /> <The-component /> </template>
-
Surcharge de la rule
vue/html-closing-bracket-newline
. Les sauts de ligne avant la fermeture des tags n'est pas autorisée.<template> <!-- ✓ GOOD --> <div id="foo" class="bar"> <div id="foo" class="bar"> <!-- ✗ BAD --> <div id="foo" class="bar" > <div id="foo" class="bar" > </template>
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
- Are Javascript functions like
map()
,reduce()
, andfilter()
optimized for traversing arrays? - Loading...
Resources
Learning ES6
- Draft ECMA 2015 (ES6) Spec
- ExploringJS
- ES6 Compatibility Table
- Comprehensive Overview of ES6 Features
Read This
Tools
- Code Style Linters
- ESlint - Airbnb Style .eslintrc
- JSHint - Airbnb Style .jshintrc
- JSCS - Airbnb Style Preset (Deprecated, please use ESlint)
- Neutrino preset - neutrino-preset-airbnb-base
Other Style Guides
- Google JavaScript Style Guide
- jQuery Core Style Guidelines
- Principles of Writing Consistent, Idiomatic JavaScript
Other 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
Further Reading
- 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
Books
- 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
- JavaScript Weekly
- JavaScript, JavaScript...
- Bocoup Weblog
- Adequately Good
- NCZOnline
- Perfection Kills
- Ben Alman
- Dmitry Baranovskiy
- Dustin Diaz
- nettuts
Podcasts