Arrays

Objects over arrays

Use object destructuring for multiple return values, not array destructuring. This allows you to add new properties over time or change the order of things without breaking call sites 3.

// badfunctionprocessInput(input){// then a miracle occursreturn[left,right,top,bottom];}// the caller needs to think about the order of return dataconst[left,__,top]=processInput(input);// goodfunctionprocessInput(input){// then a miracle occursreturn{left,right,top,bottom};}// the caller selects only the data they needconst{left,top}=processInput(input);

Types

Primitives

When you access a primitive type you work directly on its value.

string

number

boolean

null

undefined

constfoo=1;letbar=foo;bar=9;console.log(foo,bar);// => 1, 9

Complex Types

When you access a complex type you work on a reference to its value; changes to the value (as long as it’s not overwritten with a new value) will mutate the pointer value.

Trailing Commas

Do use trailing commas. This leads to cleaner git diffs. Transpilers like Babel will remove the additional trailing comma in the transpiled code, which means you don’t have to worry about the trailing comma problem in legacy browsers 6, 7.

Leading Underscores

Do not use trailing or leading underscores 13, 14. JavaScript does not have the concept of privacy in terms of properties or methods. Although a leading underscore is a common convention to mean “private”, these properties are in fact fully public, and as such, are part of your public API contract. This convention might lead developers to wrongly think that a change won’t count as breaking, or that tests aren’t needed. If you want something to be “private”, it must not be observably present; i.e. a closure.

Immutable exports

Do not export mutable bindings. Mutation should be avoided in general, but in particular when exporting mutable bindings. While this technique may be needed for some special cases, in general, only constant references should be exported 17.

// badletfoo=3;export{foo}// goodconstfoo=3;export{foo}

Default exports

In modules with a single export, prefer default export over named export 18.

// badexportfunctionfoo(){}// goodexportdefaultfunctionfoo(){}

Imports first

Put all import statements above non-import statements. Since import statements are hoisted, keeping them all at the top prevents surprising behavior 19.

Iterators and Generators

Don’t use iterators

Prefer JavaScript’s higher-order functions instead of loops like for-in or for-of2021.
You should always strive to write many small pure functions. For loops are less contained and more difficult to reason about.

Don’t use generators for now

They don’t transpile well to ES5.

Generators and Spacing

If you must use generators, or if you disregard our advice, make sure their function signature is spaced properly22. function and * are part of the same conceptual keyword - * is not a modifier for function, function* is a unique construct, different from function.