Based on the Airbnb JavaScript Style Guide.
References
Avoid using var
. If you're working with values that don't change, use const
. In other cases, use let
.
Note that both let
and const
are 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
Also, keep temporal dead zones in mind.
// const and let don't exist before they're defined.
{
console.log(a); // ReferenceError
console.log(b); // ReferenceError
let a = 1;
const b = 1;
}
Objects
Use computed property names when creating objects with dynamic property names.
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,
};
Use object method shorthand.
// bad
const atom = {
value: 1,
addValue: function (value) {
return atom.value + value;
},
};
// good
const atom = {
value: 1,
addValue(value) {
return atom.value + value;
},
};
Use property value shorthand. Group your shorthand properties at the beginning of your object declaration.
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
episodeOne: 1,
twoJediWalkIntoACantina: 2,
lukeSkywalker: lukeSkywalker,
episodeThree: 3,
mayTheFourth: 4,
anakinSkywalker: anakinSkywalker,
};
// good
const obj = {
lukeSkywalker,
anakinSkywalker,
episodeOne: 1,
twoJediWalkIntoACantina: 2,
episodeThree: 3,
mayTheFourth: 4,
};
Quote only properties that are invalid identifiers.
Arrays
Use array spreads ...
to copy arrays.
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
To convert an array-like object to an array, use Array#from.
const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);
Destructuring
Use object destructuring when accessing and using multiple properties of an object.
// 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}`;
}
Use array destructuring.
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
Use object destructuring for multiple return values, not array destructuring.
// bad
function processInput(input) {
// process the input and return necessary properties
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) {
// process the input and return necessary properties
return { left, right, top, bottom };
}
// the caller selects only the data they need
const { left, right } = processInput(input);
When programmatically building up strings, use template strings instead of concatenation.
// bad
function sayHi(name) {
return 'How are you, ' + name + '?';
}
// bad
function sayHi(name) {
return ['How are you, ', name, '?'].join();
}
// good
function sayHi(name) {
return `How are you, ${name}?`;
}
Functions
Never use arguments
; opt to use rest syntax ...
instead.
// bad
function concatenateAll() {
const args = Array.prototype.slice.call(arguments);
return args.join('');
}
// good
function concatenateAll(...args) {
return args.join('');
}
Use default parameter syntax rather than mutating function arguments.
// 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 = {}) {
// ...
}
Always put the default parameters last.
// bad
function handleThings(opts = {}, name) {
// ...
}
// good
function handleThings(name, opts = {}) {
// ...
}
Arrow functions
Use arrow functions for anonymous function expressions.
// 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;
});
If the function body consists of a single expression, omit the braces and use implicit return.
// good
[1, 2, 3].map((number) => `A string containing the ${number}.`);
// bad
[1, 2, 3].map((number) => {
return `A string containing the ${number}.`;
});
// good
[1, 2, 3].map((number) => {
const nextNumber = number + 1;
return `A string containing the ${nextNumber}.`;
});
Ensure clarity between arrow functions and comparison operators.
// 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;
};
Modules
Always use modules (import
/export
) over a non-standard module system. You can always transpile to your preferred module system.
// 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;
Variables
Group all your const declarations together and then group all your let declarations together for better readability.
// bad
let index,
total,
projectName,
data = fetchData(),
isActive = true;
// bad
let index;
const data = fetchData();
let projectName;
const isActive = true;
let total;
// good
const isActive = true;
const data = fetchData();
let projectName;
let index;
let total;
Trailing commas
Using an additional trailing comma in objects, arrays, and function parameters can lead to cleaner git diffs and improve code maintenance. Here's why:
- Cleaner Git Diffs: Adding a trailing comma minimizes the number of lines changed when new elements are added, making it easier to review code changes.
- Consistency: Ensures a consistent style in your codebase, which can improve readability.
- Transpiler Support: Transpilers like Babel will remove trailing commas in the transpiled code, ensuring compatibility with older browsers.
Example: Objects
// Bad - without trailing comma
const hero = {
firstName: 'Florence',
lastName: 'Nightingale'
};
// Good - with trailing comma
const hero = {
firstName: 'Florence',
lastName: 'Nightingale',
};
Example: Arrays
// bad
const heroes = [
'Batman',
'Superman'
];
// good
const heroes = [
'Batman',
'Superman',
];
Example: Function Parameters
// bad
function createHero(
firstName,
lastName,
isHero
) {
// ...
}
// good
function createHero(
firstName,
lastName,
isHero,
) {
// ...
}
Naming conventions
Naming functions is a critical and often challenging aspect of programming. Clear and descriptive function names improve readability and maintainability of the code. Here are some best Practices for naming functions:
Naming functions
Descriptive and Specific: Function names should clearly describe what the function does. Use verbs to name functions that perform actions. Avoid vague names.
// bad
function process() {
// ...
}
// good
function calculateTotalPrice() {
// ...
}
Avoid Abbreviations: Use full words to avoid confusion.
// bad
function calcTtl() {
// ...
}
// good
function calculateTotal() {
// ...
}
Naming variables
Use Clear and Descriptive Names:
// bad
let x = 10;
let y = 20;
// good
let width = 10;
let height = 20;
Use Meaningful Context:
Include context to avoid ambiguity.
// bad
let temp = 98;
// good
let bodyTemperature = 98;
Combining Best Practices
// bad
function calc() {
let w = 10;
let h = 20;
return w * h;
}
// good
function calculateArea() {
const width = 10;
const height = 20;
return width * height;
}