Skip to content

Coding Standards—JavaScript

Reuben L. Lillie edited this page Jul 5, 2019 · 1 revision

Use Vanilla JavaScript

JavaScript]mdn-js is the native programming language for creating dynamic web applications. Together with Hypertext Markup Language (HTML) and Cascading Style Sheets (CSS), it forms the core of the web.

JavaScript is used to handle page events, respond to user inputs, and make the browser do lots of other really cool stuff.

The term Vanilla JavaScript normally refers to JS written without relying on outside libraries like jQuery or lodash and frameworks like Angular, ReactJS, or VueJS. In the case of the electronic Manual it also means using JavaScript judiciously. For this project, VanillaJS prioritizes users with accessiblity issues, those on connections with limited bandwidth, and those restricted to older browsers or smaller screens. The good news is that well-written VanillaJS is also faster, lighter, and easier to maintain.

Learn more about JavaScript from the Mozilla Developer Network.

Learn VanillaJS tips and tricks from Christ Ferdinandi’s https://gomakethings.com/.

Functional Programming

Write short, anonymous functions. Declare them as variables with names that describe what they do. Favor functions with an explicit return statement. Utilize closures. Prefer pure functions. Make them independent when possible. Make them modular. Abstract the code base as the need arises, not before. Avoid optimizing too early. And do not, under any circumstances, write classes. This is JavaScript, not Java.

Correct:

var doSomethingCool = function () {
    return expression
}

Incorrect:

function unCool() {
    implicity inferior expression;
};

Learn more about functional JavaScript from a brief series by James Sinclair.

ES5 versus ES6+ Conventions

Use the latest ECMAScript conventions only when they can be polyfilled. Otherwise, use ES5. Do not transpile ES6 with tools like Babel for client-side use.

For information about what can and cannot be polyfilled from ES6, see Christ Ferdinandi’s VanillaJS Toolkit.

DO Use

  • Strict Mode 'use strict'
  • var
  • document.getElementById() for HTML id attribute values, but document.querySelector() and document.querySelectorAll() for classes and other selector parameters
  • Immidiately Invoked Function Expressions (IIFEs) for properly scoped independent scripts
  • Revealing Module Pattern for custom helper libraries
  • Revealing Constructor Pattern for custom plugins
  • Array.forEach() and NodeList.forEach()
  • Array.every(), Array.filter(), Array.find(), Array.from(), Array.map(), Array.reduce() Array.sort(), Array.some()
  • Promises

Do NOT Use

  • const or let
  • document.querySelector() when you could more effectively use document.GetElementById()
  • ES6 modules or Universal Module Declarations
  • Arrow functions =>
  • The ... spread operator
  • for or for ... in loops
  • Template literals (e.g ${string})
  • Keyword this (if you’re tempted, remember the electronic Manual is a community project with users of varying skill levels)

Much of ES6 is powerful and vibrant. But because the JavaScript for the electronic Manual runs in the client (i.e. browser) instead of on the server (like a Node.js app), ensuring a performant experience for users restricted to older browsers takes priority.

Learn more about backward-compatible, Vanilla JavaScript from Chris Ferdinandi’s VanillaJS Toolkit Reference.

Semicolons

Embrace JavaScript’s automatic semicolon insertion.

Omit semicolons whenever optional. (You probably inadvertently omit more optional semicolons than you think.)

In other words, don’t begin a line with an opening parenthesis, square bracket, or the any of the arithmetic operators /, +, of -. And if you must, then prepend such a line with a semicolon. In any case, do not attach semicolons to the end of variable declarations, conditionals, or function statements.

Spacing

Indent with four spaces, not tabs.

Remove whitespace at the end of lines and files.

Individual lines should aim to be shorter than 80 columns but not longer 120 columns. If indentation inhibits polite line length, consider migrating the code block to a separate function.

Put spaces around all operators. Especially for longer ternary statements, move the ? and : conditionals to separate lines.

Do not add spaces inside enclosing punctuation such as brackets {}, parentheses (), double quotes "", single quotes '', or backticks (grave accents) `.

Correct:

var doSomethingPithy = function (param) {
    return param === condition
        ? truthy
        : falsy
}

Incorrect:

function badIdea(param, otherParam) {

    var result = (( param === ( otherParam * 2) ) || (param !=  undefined) ) ?crampedTrutyCondition: poorlySpacedFalseyReturn 
    return result;

};

But do not add spaces or empty lines inside opening and closing parentheses or brackets.

Correct:

var addClassNameToElement = function (className, element) {
    return element.classList.add(className)
}

Incorrect:

var firstBodyTag = document.getElementsByTagName( "body" )[ 0 ];
function gross( adjective ) {

    var html = "<div>Who doesn’t like HTML full of " + adjective + " div tags?</div>"
    firstBodyTag.innerHTML += html;

};

Equality

Use strict equality checks (=== and !==) instead of abstract ones (== and !=).

Correct:

var isEqual = function (a, b) {
    if(a === b) return 'BINGO!'
}

Incorrect:

function notEqual( a,b ) {
    if ( b == a ) {

       return "BOTCHED!";

    } else if ( a != b ) {

       return "BOGUS!"

    }
};

Quotes

Use single quotes '. Prefer curly quotes and apostrophes . Otherwise, escape strings that contain single quotes.

Correct:

var expressGratitude = function (element) { 
    return element.textContent += ' Thank you! You’re so kind.' 
}

Incorrect:

function curmudgeon(elem) {
    var complain = "I'll use double quotes, avoid curly quotes, the serial comma and dangle prepositions if I want to!"
    var complainMore = 'And there\'s nothing you can do to stop me.'
    elem.innerHTML = complain + complainMore
}

if statements

Use if, not if else if. With multiple conditions, either list them on new lines or prefer the ternary operator.

Correct:

var handleClicks = function (event) {
    if(!event.target.classList.contains('clickable')) return
    return event.target.classList.toggle('clicked')
}
document.addEventListener('click', handleClicks, false)

Also correct:

var clickable = document.querySelectorAll('.clickable')
var handleClicks = function (event) {
    return event.target.classList.contains('clicked') 
        ? event.target.classList.toggle('clicked')
        : ''
}
clickable.addEventListener('click', handleClicks, false)

Incorrect:

document.addEventListener("click", function (e) {

    if( e.target.classList.contains("clickable" ) && e.target.classList.contains("clicked") ) {
        return e.target.classList.remove("clicked")  
    } else if (e.target.classList.contains( "clickable")) {
        return e.target.classList.add("clicked")
    } else {
        return
    }

});