JavaScript style guide

An opinionated style guide for JavaScript code.

for new codebases

never use this

functions

Always use "function expressions":

/**
 * {@link add} adds two numbers.
 * @arg {number} a
 * @arg {number} b
 * @return {number}
 */
const add = function(a, b) {
	return a + b;
};

Never use "arrow function expressions" or "function declarations".

indentation

never throw

Never throw.

Instead, return errors:

/**
 * {@link add} adds two numbers.
 * @arg {unknown} a
 * @arg {unknown} b
 * @return {number | Error}
 */
const add = function(a, b) {
	if (typeof a !== "number" || typeof b !== "number") {
		return Error("can only add numbers");
	}
	return a + b;
};

When using builtin or library functions that throw, surround them with try-catch and return the (optionally wrapped) error in the catch block.

Use Error.cause and AggregateError when appropriate.

use JSDoc for typing

do not use getters

They are great debugging tools in codebases that are not already littered with them.

always use semicolons

The alternative is "sometimes use semicolons" which is worse.

use double quotes " for strings

const vs. let (vs. var)

I don't know yet.

For now, I use const whenever I can, let otherwise. But learning about the "Temporal Dead Zone" and its performance implications in JavaScript engines have shifted me towards even considering var again.

filename

import

names

enums

Name enums like so:

/** @enum {string} */
const Color = {
	RED:   "#f00",
	GREEN: "#0f0",
	BLUE:  "#00f",
};

exceptions

All the rules above are trying to lead to a more grokkable code base. Breaking some of the rules to optimize specific parts of the code is fine.

E.g. using accessors/Proxy sparingly might be useful, but if you use them too much, it will make your code harder to grok and debug.

Using prototype sparingly, e.g. to significantly optimize memory usage of a specific kind of object with lots of instances, is fine.

But keep in mind not to optimize before measuring.

Some of the rules are mostly valuable because they demand consistency. If you're consistent the other way, e.g. using arrow functions consistently instead of using function expressions consistently, that is close to as valuable.

when working with legacy codebases

TODO