Skip to content

Latest commit

 

History

History
256 lines (189 loc) · 4.85 KB

js-coding-guidelines.md

File metadata and controls

256 lines (189 loc) · 4.85 KB
title section sortOrder
Javascript Coding Guidelines
getting-started
370

Prettier determines our code style. While Prettier's output isn't always the prettiest, it's consistent and removes all (meaningless) discussion about code style.

We try to stick to Prettier's defaults, but have a few overrides to keep our JavaScript code style consistent with PHP.

The first two rules are actually configured with .editorconfig. We use 4 spaces as indentation.

indent_size = 4

Since we use 4 spaces instead of the default 2, the default 80 character line length can be a bit short (especially when writing templates in JSX).

{
    "printWidth": 120
}

Finally, we prefer single quotes over double quotes for consistency with PHP.

{
    "singleQuote": true
}

Variable assignment

Prefer const over let. Only use let to indicate that a variable will be reassigned. Never use var.

Good:

const person = { name: 'Sebastian' };
person.name = 'Seb';

Bad:

// the variable was never reassigned
let person = { name: 'Sebastian' };
person.name = 'Seb';

Variable names

Variable names generally shouldn't be abbreviated.

Good:

function saveUser(user) {
    localStorage.set('user', user);
}

Bad:

// it's hard to reason about abbreviations in blocks as they grow.
function saveUser(u) {
    localStorage.set('user', u);
}

In single-line arrow functions, abbreviations are allowed to reduce noise if the context is clear enough. For example, if you're calling map of forEach on a collection of items, it's clear that the parameter is an item of a certain type, which can be derived from the collection's substantive variable name.

Good:

function saveUserSessions(userSessions) {
    userSessions.forEach(s => saveUserSession(s));
}

// Ok, but pretty noisy.
function saveUserSessions(userSessions) {
    userSessions.forEach(userSession => saveUserSession(userSession));
}

Comparisons

Always use a triple equal to do variable comparisons. If you're unsure of the type, cast it first.

Good:

const one = 1;
const another = "1";

if (one === parseInt(another)) {
    // ...
}

Bad:

// Bad
const one = 1;
const another = "1";

if (one == another) {
    // ...
}

Function keyword vs. arrow functions

Function declarations should use the function keyword.

Good:

function scrollTo(offset) {
    // ...
}

Bad:

// Using an arrow function doesn't provide any benefits here, while the
// `function`  keyword immediately makes it clear that this is a function.
const scrollTo = (offset) => {
    // ...
};

Terse, single line functions may also use the arrow syntax. There's no hard rule here.

Good:

function sum(a, b) {
    return a + b;
}

// It's a short and simple method, so squashing it to a one-liner is ok.
const sum = (a, b) => a + b;
export function query(selector) {
    return document.querySelector(selector);
}

// This one's a bit longer, having everything on one line feels a bit heavy.
// It's not easily scannable unlike the previous example.
export const query = (selector) => document.querySelector(selector);

Higher-order functions may use arrow functions if it improves readability.

function sum(a, b) {
    return a + b;
}

const adder = (a) => (b) => sum(a, b);

// Ok, but unnecessarily noisy.
function adder(a) {
    return function (b) {
        return sum(a, b);
    };
}

Anonymous functions should use arrow functions.

['a', 'b'].map((a) => a.toUpperCase());

Unless they need access to this.

$('a').on('click', function () {
    window.location = $(this).attr('href');
});

Try to keep your functions pure and limit the usage of the this keyword.

Object methods must use the shorthand method syntax.

Good:

export default {
    methods: {
        handleClick(event) {
            event.preventDefault();
        },
    },
};

Bad:

// The `function` keyword serves no purpose.
export default {
    methods: {
        handleClick: function (event) {
            event.preventDefault();
        },
    },
};

Object and array destructuring

Destructuring is preferred over assigning variables to the corresponding keys.

Good:

const [hours, minutes] = '12:00'.split(':');

Bad:

// unnecessarily verbose, and requires an extra assignment in this case.
const time = '12:00'.split(':');
const hours = time[0];
const minutes = time[1];

Destructuring is very valuable for passing around configuration-like objects.

function uploader({
    element,
    url,
    multiple = false,
    beforeUpload = noop,
    afterUpload = noop,
}) {
    // ...
}

The above are sections taken from the Spatie Javascript Code Guidelines.