-
Notifications
You must be signed in to change notification settings - Fork 20
Code standards: JS
The status of this document is currently Adopted.
The following is our style guide for writing JavaScript. All JS contributions MUST adhere to this document unless there's a good reason not to; such reasons MUST have a linter ignore applied to them, and SHOULD be documented using a comment above the relevant code.
This guide uses RFC 2119 terminology.
Use UTF8 encoding, without BOM. Ensure your editor is set to use UTF8 w/o BOM.
Use features of ES6 or above where they are available. Prefer modern constructs over equivalents from previous language versions. Code will be transpiled to ES5 for builds, so we can use modern features without worrying about browser compatibility. Particularly:
- Use
const
, notvar
. Uselet
if your variable will be re-assigned. - Use arrow functions,
() => {}
, where possible. Only usefunction
if athis
context is necessary. - Use
async
/await
, not callbacks orPromise
. Only use a callback when calling an API that does not offerasync
.
Write code in ES6 modules. Group related functionality (such as code relating to posts routes) into a single file; split it into multiple files if the file becomes excessively long. Use import
/export
to reference code from other files.
Name all variables and methods using lowerCamelCase
. SHOUTY_CASE
may be used for constants (true constants only, not just all const
variables).
Name files in lisp-case
, using a .js
extension: mod-dashboard.js
.
- Indent code by four spaces. Do not use tab stops.
- Always use a space on both sides of an operator, including in assignments and declarations:
1 + 1
,const foo = 'bar';
,() => {}
. - Use a space between parameters in function declarations and calls:
(foo, bar) => { }
,sendFormData(form, 'POST')
. - Use a space between key and value when declaring object literals, and between each pair:
const data = {a: 1, b: 2};
- Use a space between control flow keywords and the opening parenthesis; as well as between the closing parenthesis and the opening brace:
if (x === 1) {
. - Do not use a space between function definitions or function calls and the opening parenthesis:
function getUsersByGroup(groupId)
;let users = getUsersByGroup(1)
. - Do not use spaces inside parentheses:
(x === 1)
, not( x === 1 )
- Do not write more than one statement per line.
- Semicolons must not be omitted at the end of statements.
- Braces must not be omitted for single-line statements following a control flow expression (e.g.
if
/else
,for
,while
). - Equality checks must use strict equality checking (
===
). The only exception is when checking for null/undefined values, which may be written asif (value == null)
.
Prefer double quotes. If a quoted string contains a literal double quote character, use single quotes instead:
const mergeTargetModal = document.querySelector("#js-merge-target-select");
const groupLinks = document.querySelectorAll('[data-type="type_group"] > a');
Use of template literals is allowed where it makes sense.
Do not write lines longer than 120 characters. Lines that would be longer than 120 characters must be hard-wrapped onto the next line, and every continuation line must be indented at least one more level than the first line. Wrapped lines may be indented further to align certain elements with one another.
codidact.createDangerConfirmationAudit(document.querySelectorAll('.modal.is-danger > .modal--body'),
'POST', 'https://codidact.org/audits/danger-confirmation');
Follow the K&R style of bracing:
- No line break before opening brace
- Line break after opening brace
- Line break before closing brace
- Line break after closing brace
A blank line must also be added after a closing brace where the brace closes a function, method, or class body.
class ModalDialog {
constructor(data) {
if (Object.keys(data).length > 0) {
this.dataset = data;
}
else {
this.dataset = {};
}
}
get name() {
return this.dataset['name'] || '(none)';
}
}
When assigning one of two possible values to a variable according to a condition, prefer the ternary operator (?:
):
this.dataset = (Object.keys(data).length > 0) ? data : {};
Note the use of parentheses around the conditional expression - it makes it more obvious at first glance that this is a conditional statement. This is a requirement.
For very long or deeply indented expressions that exceed the 120-char line length limit (item 8), use the following line-break and indenting style:
this.dataset = (Object.keys(data).length > 0 && data.includes("email")
&& data["createdAt"] >= someLongDateTimeString)
? data
: {};
When assigning to multiple variables according to the same condition, do not use a ternary expression. The if / else
block should be used instead (remember: don't repeat yourself).