A mostly reasonable approach to JavaScript
Fork from Airbnb style guide
Other Style Guides
- Types
- References
- Objects
- Arrays
- Destructuring
- Strings
- Functions
- Arrow Functions
- Classes & Constructors
- Modules
- Iterators and Generators
- Properties
- Variables
- Hoisting
- Comparison Operators & Equality
- Blocks
- Comments
- Whitespace
- Commas
- Semicolons
- Type Casting & Coercion
- Naming Conventions
- Accessors
- Events
- jQuery
- ECMAScript 5 Compatibility
- ECMAScript 6+ (ES 2015+) Styles
- Testing
- Performance
- Resources
- In the Wild
- Translation
- The JavaScript Style Guide Guide
- Chat With Us About JavaScript
- Contributors
- License
-
1.1 Primitives: When you access a primitive type you work directly on its value.
stringnumberbooleannullundefined
const foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
-
1.2 Complex: When you access a complex type you work on a reference to its value.
objectarrayfunction
const foo = [1, 2]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
-
2.1 Use
constfor all of your references; avoid usingvar. eslint:prefer-const,no-const-assignWhy? This ensures that you can't reassign your references, which can lead to bugs and difficult to comprehend code.
// bad var a = 1; var b = 2; // good const a = 1; const b = 2;
-
2.2 If you must reassign references, use
letinstead ofvar. eslint:no-varjscs:disallowVarWhy?
letis block-scoped rather than function-scoped likevar.// bad var count = 1; if (true) { count += 1; } // good, use the let. let count = 1; if (true) { count += 1; }
-
2.3 Note that both
letandconstare block-scoped.// 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
-
3.1 Use the literal syntax for object creation. eslint:
no-new-object// bad const item = new Object(); // good const item = {};
-
3.2 Use computed property names when creating objects with dynamic property names.
Why? They allow you to define all the properties of an object in one place.
function getKey(k) { return `a key named ${k}`; } // bad const obj = { id: 5, name: 'San Francisco', }; obj[getKey('enabled')] = true; // good const obj = { id: 5, name: 'San Francisco', [getKey('enabled')]: true, };
-
3.3 Use 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.4 Use property value shorthand. eslint:
object-shorthandjscs:requireEnhancedObjectLiteralsWhy? It is shorter to write and descriptive.
const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { lukeSkywalker: lukeSkywalker, }; // good const obj = { lukeSkywalker, };
-
3.5 Group your shorthand properties at the beginning of your object declaration.
Why? It's easier to tell which properties are using the shorthand.
const anakinSkywalker = 'Anakin Skywalker'; const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, lukeSkywalker, episodeThree: 3, mayTheFourth: 4, anakinSkywalker, }; // good const obj = { lukeSkywalker, anakinSkywalker, episodeOne: 1, twoJediWalkIntoACantina: 2, episodeThree: 3, mayTheFourth: 4, };
-
3.6 Only quote properties that are invalid identifiers. eslint:
quote-propsjscs:disallowQuotedKeysInObjectsWhy? In general we consider it subjectively easier to read. It improves syntax highlighting, and is also more easily optimized by many JS engines.
// bad const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5, }; // good const good = { foo: 3, bar: 4, 'data-blah': 5, };
-
3.7 Do not call
Object.prototypemethods directly, such ashasOwnProperty,propertyIsEnumerable, andisPrototypeOf.Why? These methods may be shadowed by properties on the object in question - consider
{ hasOwnProperty: false }- or, the object may be a null object (Object.create(null)).// bad console.log(object.hasOwnProperty(key)); // good console.log(Object.prototype.hasOwnProperty.call(object, key)); // best const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope. /* or */ import has from 'has'; // ... console.log(has.call(object, key));
-
3.8 Prefer the object spread operator over
Object.assignto shallow-copy objects. Use the object rest operator to get a new object with certain properties omitted.// 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 }
-
4.1 Use the literal syntax for array creation. eslint:
no-array-constructor// bad const items = new Array(); // good const items = [];
-
4.2 Use Array#push instead of direct assignment to add items to an array.
const someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra');
-
4.3 Use array spreads
...to copy arrays.// bad const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i += 1) { itemsCopy[i] = items[i]; } // good const itemsCopy = [...items];
-
4.4 To convert an array-like object to an array, use Array.from.
const foo = document.querySelectorAll('.foo'); const nodes = Array.from(foo);
-
4.5 Use return statements in array method callbacks. It's ok to omit the return if the function body consists of a single statement following 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] = 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; });
- 4.6 Use line breaks after open and before close array brackets if an array has multiple lines
// bad
const arr = [
[0, 1], [2, 3], [4, 5],
];
const objectInArray = [{
id: 1,
}, {
id: 2,
}];
const numberInArray = [
1, 2,
];
// good
const arr = [[0, 1], [2, 3], [4, 5]];
const objectInArray = [
{
id: 1,
},
{
id: 2,
},
];
const numberInArray = [
1,
2,
];-
5.1 Use object destructuring when accessing and using multiple properties of an object. jscs:
requireObjectDestructuringWhy? Destructuring saves you from creating temporary references for those properties.
// 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}`; }