A Guide to Enhanced Readability with semi-colons in ES6
The latest flavor of JavaScript has brought more syntactical features than any other. It has also removed (or deprecated) syntax that many JavaScript developers grew up with! Does that mean we completely throw it out? Some developers certainly think so, but I say no~! Even Google’s summarized ES6 style guide continues to require semi-colons. There is a good reason.
As developers we should know that when you remove a feature there will inevitably be users who relied on that feature to help them accomplish their task (in this case, we all program and write code :)). So let’s ask the question, what are semi-colons useful for and what are they used for in ES5?
Currently, in order of priority and importance, below are the general rules for ES5:
- Include semi-colons at the end of each line that is a variable declaration using const, let, or var.
- Include semi-colons at the end of each statement that does a simple execution of code and does NOT contain curly braces. So any statement with these babies, {}, does not need a semi-colon UNLESS it’s a variable declaration — rule 1 above. Simple console.log statements would need semi-colons and so would changing the value (mutating) a variable. However, if you are declaring a variable that is an object-literal, remember you DO include a semi-colon even though an object literal has curly braces.
- Do NOT include semi-colons at the end of function declarations, loops, classes, and constructors.
Where semi-colons are allowed is just as informative as where they are not allowed. So if you don’t see a semi-colon at the end of a line that ends in a curly brace, it’s probably the function you saw earlier. If you DO see a semi-colon at the end of a line with a curly brace, it’s the object literal that was declared a few lines ago.
Given the tendency of JavaScript code to get nested, despite all our fancy talk of promises, promise chaining, reactive functional programming, and advanced technological wizardry that would put Merlin to shame, there will still be nesting. Always. This means removing semi-colons completely is dangerous for readability. However, since they are no longer syntactically required, we can create a different set of guidelines for them that enhance readability.
Below is a list of practical DO’s and DON’Ts for enhanced readability in ES6 using semi-colons. They are inspired by the ES5 requirements, adjusted for new ES6 syntax like arrow functions, classes, JSX, and class components. There are different levels of readability you can aim for. The minimal level of readability is complying with ES5 semi-colon syntax.
DO’s
- Use semi-colons at the end of each variable assignment that is not a function: This lets developers distinguish between actual constants, and arrow functions (which often also use the keyword const). Also note that sometimes in TypeScript you may need to just declare the variable with a type before knowing what the value is. You DO NOT need to add a semi-colon here because the variable is not yet assigned.
- Use semi-colons at the end of return statements: This is especially helpful within the context of JS frameworks like react where a return statement can take up the whole function. It helps spot the difference between when the function logic ends and when the actual function ends.
- Use semi-colons at the end of function calls: This helps us spot when we are creating a side-effect. For more advanced use cases, you can include semi-colons at the end of impure function calls to help better spot side effect inducing logic for a more enhanced debugging experience.
Examples:
// Variable assignments
const radius = 2;
const height = 5;// Arrow function declaration - NO semi-colon because a function()
// does not have a semi-colon at the end in ES5.
const areaCircle = (rad) => {
return Math.pi * rad * rad; // return statement semi-colon} // NO semi-colon!!
const volCylinder = (rad, ht) => {
return areaCircle(rad) * ht;}console.log(volCylinder(radius, height));
Note that if we followed ES5 syntax to the dot, every closing brace would have aa semi-colon after it in the above code. Let’s take a look at do not’s.
DO NOT’s
- Don’t use semi-colons at the end of function and class declarations: Same as in ES5, except for functions and classes, includes arrow syntax even though it has an equal (=) sign because it often feels like it’s replaced the default function() declaration.
- Don’t use semi-colons at the end of class method declarations: ES5 didn’t support it, and we shouldn’t add it back in ES6 either.
- (Optional) Don’t use semi-colons at the end of method calls in the same class: This relates to the pure function guideline from the third “DO”. Since a class method is part of the same level of abstraction, even if it is impure, it’s optional to add a semi-colon at the end because it’s a reference to a localized value.
Examples (Using React):
import React, {Component} from 'react';export const FunctionalButtonComponent = (props) => {
return <button className={props.className}>{props.title}</button>;} // no semi-colonexport class ClassInput extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = { value: '' }; }
handleChange(event) {
const { value } = event.target; // optional semi-colon exclusion for internal method calls
this.setState({ value }) } render() {
return <input onChange={this.handleChange} value={this.state.value}/>; }}
The three guidelines above are framed around being able to easily find code that is a likely source of bugs. Variable assignments, impure functions, and complex return statement logic are three of the most likely culprits for introducing bugs. Now that ES6 has given us the freedom in how to use semi-colons, let’s use them to enhance the readability of our code and make better software that will survive the test of time.