Categories
JavaScript Best Practices

JavaScript Best Practices — Using Libraries and Shortcuts That are Clear

Like any other programming language, JavaScript has its own list of best practices to make programs easier to read and maintain. There are a lot of tricky parts to JavaScript, so there are things we should avoid that reduce the quality of our code. By following best practices, we can create elegant and manageable code that’s easy for anyone to work with.

In this article, we look at using libraries, using shortcuts that make sense, short ways to build a string from an array, and being aware of the difference between development and live code.

Use Libraries When They Exist

If somebody already made a library to do something that we want to do, we should use the library instead of writing everything from scratch again.

Reinventing the wheel is a time-consuming process, then testing all the cases takes even longer.

This means that we should use libraries to speed up software development and not reinvent the wheel.

Nowadays, client-side apps are more complex than ever, with users expecting slick user experiences in the apps we write. This means writing everything from scratch is pretty much impossible.

This is why frameworks like Angular, React and Vue are becoming more and more popular. There’s no going back to the bad old days where everything is written in plain JavaScript.

Front end development isn’t just adding a few things on top of our back end apps anymore.

However, when we’re learning JavaScript, we should still learn by writing plain JavaScript code first to learn the principles that make these libraries and framework work.

Nowadays, client-side apps are complex enough that it’s hard to avoid using lots of libraries to build something functional.

Difference Between Development Code and Live Code

The codebase that we read and write shouldn’t be mistaken for the code that’s run.

Most browsers optimize the code if we follow the best practices that are listed all over the online community.

Browsers convert the code we write to machine code on run-time to make it run faster.

Also, lots of client-side apps now have a build process associated with it to optimize the code by minifying it and combining redundant code into one place, etc.

This means that we should build code for readability and maintainability rather than trying to make hard to read code that we think will make it run faster.

Browsers no longer run code line by line from script files anymore.

Use Shorthand When They Make Sense

Some of the older shorthands in JavaScript are confusing. For example, if we run the following code:

if(false)  
   var x = false  
   let y = 0  
console.log(x, y)

We get undefined and 0 logged. undefined makes sense, but why is y 0? This is because the declaration of y actually doesn’t belong to the if block.

As we can see, the if statement without curly braces is confusing. Only the first line after the if statement is considered to be inside the if block.

Therefore, we should always wrap our if blocks with curly braces.

Another problem with the code snippet above is that we don’t have semicolons. This is another problem because when don’t know where the line ends. It’s better to just make it clear by putting in the semicolon at the end.

However, since ES6, we have lots of shorthands that are very useful and aren’t confusing.

For example, the spread and rest operators are very useful for copying or combining objects and getting arguments in an array respectively.

The spread operator can be used as follows:

const obj1 = { foo: 1, bar: 2 }, obj2 = { baz: 3 };  
const obj3 = { ...obj1, ...obj2 };

Then we get obj3 having the value:

{ foo: 1, bar: 2, baz: 3 }

The rest operator uses the same 3 dots, but works on functions. For example, we can write a function with the rest operator as follows:

const add = (a, b, ...rest) => {  
  return a + b + rest.reduce((a, b) => a + b, 0);  
}

Where ...rest is has an array with the arguments other than the first 2.

Then we can call it as follows:

console.log(add(1, 2));  
console.log(add(1, 2, 3));  
console.log(add(1, 2, 3, 4, 5));

And we get 3, 6, and 15 respectively.

Another handy and clear shortcut is the destructuring assignment syntax. It works on both objects and arrays. For example, we can destructure an array into variables as follows:

const [a, b] = [1, 2];  
console.log(a, b);

Similarly, with objects, we can write:

const {  
  foo,  
  bar  
} = {  
  foo: 1,  
  bar: 2  
};  
console.log(foo, bar);

We get 1 and 2 for a and b respectively in both examples.

Shortest Way to Building a String

There’re multiple ways to build a string from an array of strings in JavaScript. One way is to use a loop as follows:

const arr = ['foo', 'bar', 'baz'];  
let str = '';  
for (let i = 0; i < arr.length; i++) {  
  str += arr[i];  
  if (i !== arr.length - 1) {  
    str += ',';  
  }  
}

The other way is to use the join method built into array objects:

const arr = ['foo', 'bar', 'baz'];  
let str = arr.join(',');

As we can see, the loop is much more complex and are much more prone to errors because of it. We’ve to loop through the array, concatenate each entry, and then add a comma after it if it’s not the last entry.

On the other hand, the join method just joins the array entries with a comma with one line.

Today’s JavaScript apps are more complex than ever. This is why we should use libraries and frameworks to build apps to make our lives easier.

This also means that we should be writing code that makes development easy rather than thinking about how to accommodate browsers. However, we should still think about performance when writing the code.

Also, we should also use shortcuts that makes development and reading the code easy. Most shortcuts introduced with ES6 or later have both of these characteristics. Older shortcuts like writing if statements without curly braces are not.

Finally, we should use existing methods to simplify code. For example, when making a comma-separated string from an array of strings, we can use the join method instead of writing a loop to do it.

Categories
JavaScript Best Practices

JavaScript Best Practices — Browser Differences, Performance and More

Like any other programming language, JavaScript has its own list of best practices to make programs easier to read and maintain. There are a lot of tricky parts to JavaScript, so there are things we should avoid that reduce the quality of our code. By following best practices, we can create elegant and manageable code that’s easy for anyone to work with.

In this article, we’ll look at how to gracefully support old browsers, avoiding heavy nesting, various optimizations, and checking the data in our programs.

Progressive Enhancement

Progress enhancement means that we should degrade our app gracefully when some technology isn’t available. This means that we should check if some technology is supported in all the browsers that we want to support and keep our app working in some way if it doesn’t.

We can also add polyfills to add support for new technologies that older browsers that we support don’t have.

For example, if we want to use new array methods that aren’t available in Internet Explorer 11 but our app still supports the browser, then we have to add a polyfill for it or check for its existence and do something different instead of crashing.

Avoid Heavy Nesting

Having lots of nesting in code makes them very confusing to read. This is because it’s very hard to follow the logic of the code.

Nesting conditional statements and loops should be kept to a minimum.

For example, instead of writing:

const items = {
  foo: [1, 2, 3],
  bar: [1, 2, 3],
  baz: [1, 2, 3]
};

const parentUl = document.createElement('ul');
for (const item of Object.keys(items)) {
  const parentLi = document.createElement('li');
  const childUl = document.createElement('ul');
  for (const num of items[item]){
    const childLi = document.createElement('li');
    childLi.textContent = num;
    childUl.appendChild(childLi);
  }
  parentLi.textContent = item;
  parentLi.appendChild(childUl);
  parentUl.appendChild(parentLi);
}
document.body.appendChild(parentUl);

This creates a nested list, which is confusing to read and write. We should reduce nesting by separating the list creating into a function and call the function instead:

const items = {
  foo: [1, 2, 3],
  bar: [1, 2, 3],
  baz: [1, 2, 3]
};

const createUl = (items) => {
  const ul = document.createElement('ul');
  for (const item of items) {
    const li = document.createElement('li');
    li.textContent = item;
    ul.appendChild(li);
  }
  return ul;
}

const parentUl = createUl(Object.keys(items));
const parentLis = parentUl.querySelectorAll('li');
for (const parentLi of parentLis) {
  const childUl = createUl(items[parentLi.textContent]);
  parentLi.appendChild(childUl);
}
document.body.appendChild(parentUl);

As we can see, the code above doesn’t have any nested loops, which makes the code easier to read. Also, we have a createUl function to create the ul element with entries inside and returns the ui element object.

This means that we can attach it however we like to the document or an HTML element afterward.

Optimize Loops

We should cache values that are used in every literation in a single variable.

This is because every time we do this, the CPU has to access the item in memory again and again to compute its results.

Therefore, we should do this as little as possible.

For example, if we have a loop, we shouldn’t write the following:

for (let i = 0; i < arr.length; i++) {

}

Instead, we should write:

let length = arr.length;
for (let i = 0; i < length; i++) {

}

This way, arr.length is only referenced once in our loop instead of accessing it in every iteration.

Photo by Adrien CÉSARD on Unsplash

Keeping DOM Access to a Minimum

DOM manipulating is a CPU and memory-intensive operation. Therefore, we should strive to keep it to a minimum.

This means we have to keep pages as simple as possible and only do DOM manipulation when it’s necessary. Any static styles should be in CSS and not added on the fly with JavaScript.

Also, we should keep any static elements in HTML and not create them by manipulating the DOM.

Also, we should make functions that create elements and call them when we need to rather than continuously doing DOM manipulating operations on the top-level of the code.

Write Code for All Browsers

All browsers should get the same treatment by our code. We shouldn’t write hacks to accommodate various browsers because these hacks will be broken quickly when the browser changes versions.

We should stick to code that’s are accepted as standards or use libraries like Modernizr to deal with issues with different browsers.

Also, we can add polyfills to add any functionality that is missing in various browsers, so we can keep our app running on different browsers even though there’s they might not support some functionality out of the box.

Don’t Trust Any Data

We should check for any data that’s inputted by the user. HTML5 has lots of form validation functionality to check for valid inputs. We can do it with HTML5 and plain JavaScript.

Once we check for the inputted data, we also need to check for data in variables and returned from functions. Since JavaScript is a dynamically typed language, we’ve to check for these things.

For primitive values, we can use the typeof operator to check the data type of data. For example, if we have:

let x = 1;

Then typeof x will return 'number' . Other primitive data types like boolean, strings, undefined, etc. are the same.

The only exception is null , which has the type object.

We should always check for values like null or undefined since they might crash our program. We can do that by writing x === null and typeof x === 'undefined' respectively.

Also, we should be careful of type coercions done by JavaScript, like in conditional statements and function calls. For example, the Math.min method converts its arguments to numbers when it’s called. The == operator converts all the operands to the same type before returning the result.

For objects, we can check for their type by using the instanceof operator to see which constructor they’re created from. For example, if we have an array:

let arr = [];

Then [] instanceof Array will be true . Arrays also have a static isArray method to check for the data type.

In the JavaScript code, we write, we should be aware of the differences in different browsers that our app supports. This means checking if the methods that we want to use exist and adding polyfills to add missing functionality for older browsers.

We should cache variables and properties that are accessed repeatedly in loops so they don’t have to be accessed each time the loop runs.

Deep nesting should also be avoided to keep code clear and easy to follow.

Also, since DOM manipulation is an expensive operation, it should be kept to a minimum. Static styles and elements should be in CSS and HTML respectively.

Finally, we shouldn’t trust the data in our apps. Inputs have to be checked for format and validity, and data in our variables and values should be checked for type, including null or undefined .

Categories
JavaScript Best Practices

JavaScript Best Practices — Performance

Like any other programming language, JavaScript has its own list of best practices to make programs easier to read and maintain. There are a lot of tricky parts to JavaScript, so there are things we should avoid that reduce the quality of our code. By following best practices, we can create elegant and manageable code that’s easy for anyone to work with.

In this article, we’ll look at ways to improve the performance of our apps. Actions include caching data in variables, using the fastest way to loop through variables, reducing DOM access and elements on the page, and deferring script loading.

Reduce Access to Variables and Properties

We should reduce the times that we access variables and object properties in our apps.

This is because every time we do this, the CPU has to access the item in memory again and again to compute its results.

Therefore, we should do this as little as possible.

For example, if we have a loop, we shouldn’t write the following:

for (let i = 0; i < arr.length; i++) {

}

Instead, we should write:

let length = arr.length;
for (let i = 0; i < length; i++) {

}

This way, arr.length is only referenced once in our loop instead of accessing it in every iteration.

Fastest Way to Loop Through Variables

In JavaScript, there’re multiple ways to iterate through iterable objects. One is the good old for loop. Other ways include the for...of loop, the forEach method for arrays. map and filter also loop through the array as the map and filter operations are being done. There’s also the while loop.

Of all the ways to run loops, the for loop is the fastest way, with or without caching the length like we did above. Caching the length sometimes makes the loop performs better, however.

Some browser engines have optimized the for loop without caching the length property.

The while loop with decrementing index is approximately 1.5 times slower than the for loop

Using the forEach loop is 10 times slower than the for loop, so it’s probably better to avoid it, especially for large arrays.

We can see the results here.

Reduce DOM Access

Accessing the DOM is an expensive operation since the browser has to grab the element from the web page and then create an object from it and return it.

To reduce DOM access, we should set the DOM Node objects to a variable if we need to manipulate it more than once.

For example, if we have the following HTML and we want to set some text to it after a few seconds:

<p id='foo'>

</p>

We can write the following code to do so:

const setText = (element, textContent) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      element.textContent = textContent;
      resolve();
    }, 3000)
  })
}

(async () => {
  const foo = document.querySelector('#foo');
  await setText(foo, 'foo');
  await setText(foo, 'bar');
  await setText(foo, 'baz');
})();

In the code above, we have one function which gets the HTML element that we want to manipulate, and the text content that we want to set.

The setText function returns a promise to set the text to a given element after 3 seconds.

Then we have an async function to set the text 3 times. The important part is that we pass in the reference to the element in each call. This way we don’t have to get the element from the web page 3 times, which is an expensive operation.

Photo by Sawyer Bengtson on Unsplash

Reduce DOM Size

Rendering the DOM tree is slow. Therefore, we have to reduce the size of the tree.

There’s no way around it but to make our web pages as simple as possible.

Having a smaller DOM make searching for elements with methods like querySelector, getElementById, or getElementsByTagName faster since there’s less to look for.

Also, page rendering performance will improve since there’s less to load. This is especially true for slower devices like phones and tablets.

Don’t Declare Unnecessary Variables

Every time we declare variables, the browser has to reserve memory space for the variables. Therefore, to reduce memory usage, we should declare too many variables.

For example, if we have the following HTML:

<div id='foo'>
  <p>

  </p>
</div>

And we want to set the text content of the p element, we shouldn’t write something like:

const foo = document.querySelector('#foo');
const p = foo.querySelector('p');
p.textContent = 'foo';

since we have 2 variables. This means our computer has to store the values for 2 more JavaScript variables.

Instead, we can reduce to no variable declarations by writing:

document.querySelector('#foo p').textContent = 'foo';

As we can see, we can use the querySelector method to select anything with CSS selectors. This means that we should use this method and the related querySelectorAll method to select elements since they can both use CSS selectors to select any HTML element node.

Defer the Loading of Scripts

Loading JavaScript files is an expensive operation. The browser has to download the file, parse the content, and then convert it to machine code and run it.

The browser will download one file at a timeline by line, so it’ll hold up any other operation from happening.

Therefore, we should delay it as much as we can. We can do this by putting the script tag to the end. Also, we can use the defer attribute on the script tag to do this.

Also, we can run scripts after the page is loaded by create script elements on the fly and appending it as follows:

window.onload = () => {
  const element = document.createElement("script");
  element.src = "https://code.jquery.com/jquery-1.12.4.min.js";
  document.body.appendChild(element);
};

Anything that can be loaded after the page loads can use this method of script loading.

We can speed up our pages by doing a few things. First, we can cache data in variables so we don’t have to access them repeatedly. Then we can loop through items faster with the for loop.

Also, we can reduce the DOM size to reduce the items that need to be loaded. We can also cache DOM objects in our code by assigning them to variables.

We also should not declare unnecessary variables, and we should defer the loading of scripts as much as possible so it won’t hold up our browser.

Categories
JavaScript Best Practices

JavaScript Best Practices — DOM Manipulation and Functions

Like any other programming language, JavaScript has its own list of best practices to make programs easier to read and maintain. There are a lot of tricky parts to JavaScript, so there are things we should avoid that reduce the quality of our code. By following best practices, we can create elegant and manageable code that’s easy for anyone to work with.

In this article, we’ll look at ways to reduce DOM manipulation, use shortcut notation, and having functions perform a single task.

Avoid DOM Manipulation

In our JavaScript, we should avoid manipulating the DOM if we want to display something dynamically. We can easily put a lot of styling code in our CSS instead of manipulating it directly with JavaScript.

For example, if we want to make an input display a red border when the input is invalid on submit, we can write the following HTML code:

<form>
  <input type='text' required>
  <button type='submit'>
    Submit
  </button>
</form>

Along with the following JavaScript code:

const input = document.querySelector('input');
const form = document.querySelector('form');

form.onsubmit = (e) => {
  e.preventDefault();
}

input.oninvalid = () => {
  input.style.borderColor = 'red';
  input.style.borderStyle = 'solid';
  input.style.borderWidth = '1px';
}

As we can see, in the event handler we assigned to the oninvalid property of the input, we set the border with JavaScript.

However, we can instead do it with CSS by creating a class and setting the class name in JavaScript instead.

We keep the same HTML code, but add the following CSS code:

.invalid {
  border: 1px solid red;
}

Then in our JavaScript code, we replace what we had with:

const input = document.querySelector('input');
const form = document.querySelector('form');

form.onsubmit = (e) => {
  e.preventDefault();
}

input.oninvalid = () => {
  input.className = 'invalid';
}

As we can see, it does the same thing in a much shorter way. It requires less processing power since it isn’t setting the styles dynamically.

Also, now we have a class and style that we can reuse in other HTML elements so that we don’t have to repeat code.

Using Shortcuts

In JavaScript, there are lots of shortcuts that are still clear for developers to read.

For example, when we create an object, we can either use the Object constructor or the object literal notation.

With the Object constructor, we can create an object as follows:

let obj = new Object();
obj.foo = '1';
obj.bar = '2';
obj.baz = function() {
  console.log('baz');
}

Alternatively, we can write the same thing in the object literal notation:

let obj = {
  foo: '1',
  bar: '2',
  baz() {
    console.log('baz');
  }
}

We have the same number of lines, but we have to repeat the object name in every line in the first example. Whereas we don’t have to do that with the object literal.

Object literals also improve clarity, so we can use that instead of the Object constructor to create an object. They both do the same thing, but we don’t have to repeat code as we did by creating an object with the Object constructor.

Likewise, instead of defining an array as follows:

let arr = new Array();
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;

We can define it in a much shorter way by writing:

let arr = [1, 2, 3, 4, 5];

As we can see, it’s way shorter to define it with the array literal than the Array constructor. Also the Array constructor is confusing since it has 2 signatures. If we pass in one argument, then we get the array with the length set by the argument. Otherwise, we get an array with the arguments we passed in as the content.

Another handy shortcut is the ternary operator, where we can assign things to a variable conditionally.

For example, instead of writing:

const x = 100;
let foo;
if (x === 100) {
  foo = 'bar';
} else {
  foo = 'baz';
}

We can write:

const x = 100;
let foo = (x === 100) ? 'bar' : 'baz';

In the code above:

let foo;
if (x === 100) {
  foo = 'bar';
} else {
  foo = 'baz';
}

is the same as:

let foo = (x === 100) ? 'bar' : 'baz';

They both check if x is 100 then, then assign 'bar' to foo if it is, and assign 'baz' otherwise.

The code is much shorter with the ternary operator and we get the same result. It also doesn’t make the code harder to read.

Photo by Austin Distel on Unsplash

One Function Per Task

Generally, a function should only do one thing. This makes each function short and easy to read.

It also makes reusing it easier since there’s less chance of conflicting functionality in each function.

Also, it’s a good idea to create helper functions for common tasks.

For example, if we want to create some elements on the fly on a page. Either we can write:

const createPage = () => {
  const items = ['foo', 'bar', 'baz'];
  const ul = document.createElement('ul');
  let li;
  for (const item of items) {
    li = document.createElement('li');
    li.textContent = item;
    ul.appendChild(li);
  }
  document.body.appendChild(ul);

  const googleLink = document.createElement('a');
  googleLink.href = '[http://www.googole.com'](http://www.googole.com%27);
  googleLink.textContent = 'Google';
  document.body.appendChild(googleLink);

  const yahooLink = document.createElement('a');
  yahooLink.href = '[http://www.yahoo.com'](http://www.yahoo.com%27);
  yahooLink.textContent = 'Yahoo';
  document.body.appendChild(yahooLink);
}

createPage();

Or we can write:

const createLink = (textContent, href) => {
  const link = document.createElement('a');
  link.href = href;
  link.textContent = textContent;
  return link;
}

const createUl = (items) => {
  const ul = document.createElement('ul');
  let li;
  for (const item of items) {
    li = document.createElement('li');
    li.textContent = item;
    ul.appendChild(li);
  }
  return ul;
}

const items = ['foo', 'bar', 'baz'];
const ul = createUl(items);
const googleLink = createLink('Google', '[http://www.google.com'](http://www.google.com%27));
const yahooLink = createLink('Google', '[http://www.yahoo.com'](http://www.yahoo.com%27));
document.body.appendChild(ul);
document.body.appendChild(googleLink);
document.body.appendChild(yahooLink);

We should write it the second way because we divide our code into functions that always return the same thing given the same input.

Also, they can be called anywhere. So if we want another link we can call createLink again for example.

We also return the element, so we can attach it outside the functions, which means we can create elements on the fly without attaching them right away.

Conclusion

When we deal with client-side JavaScript code, we should avoid DOM manipulation as much as possible for increased performance and less code complexity.

Also, lots of JavaScript shortcuts make sense, like using literals whenever they’re available instead of the constructor.

Finally, we should divide code into functions that each does a single task to keep things easy to read and maintain. It also makes functions easier to reuse since they don’t have conflicting functionality.

Categories
JavaScript Best Practices

JavaScript Best Practices — Naming, Style, and Comments

Like any other programming language, JavaScript has its own list of best practices to make programs easier to read and maintain. There are lots of tricky parts to JavaScript, and this means there are certain patterns or features we should avoid. We can follow some best practices to make our JavaScript code easy to read.

In this article, we’ll look at some best practices for styling code to be easy to read. We look at variable and function naming, avoiding global variables, keeping a strict coding style, and commenting code in moderation.

Easy, Short, and Readable Names for Variables, Functions, and Classes

Function names should be short and meaningful. For example, if we want to create a variable to store someone’s birthday, it should have a name that indicates that.

This means that it shouldn’t be a name like b, but it also shouldn’t be something with extraneous words like veryVeryVeryLongBirthdayName. Naming it birthday would be appropriate.

Also, something to avoid is combining value with functionality in names. For example, if we want to write a function to check if someone is over the age of majority, we should name it something like isAdult() instead is isOverEighteen().

This also makes more sense since not every place has age 18 as the age of majority.

We can also consider Hungarian notation for naming variables and functions. The notation combines both the return type and the name into one. Since JavaScript function doesn’t have a fixed return type, we can add a prefix for the type for the function.

For example, if we want to return a boolean with our isAdult() function, we can write bIsAdult() with the b indicating that it’s a boolean.

Keeping names in English is also a good idea since it keeps everything consistent with the rest of the code. All the reserved words like function and new are all in English, so it’s consistent to keep everything else in English.

English is also a more international language so it’s more likely that developers know English than not.

Classes are functions that construct other objects, so their naming should reflect that. For example, if we have a class that construct person objects, then they should be named Person.

Class names should be upper case and indicates what kind of object we’re creating from it.

Avoid Global Variables and Functions

In JavaScript, everything runs in the file runs in the same scope. This is a real problem because things can easily be accidentally modified and referenced unintentionally.

Fortunately, since ES6, JavaScript has several features to deal with this. One is the use of modules. With modules, only the things that we explicitly export are available for other modules to use.

JavaScript strict mode should also be enabled to prevent the accidental declaration of global variables. With strict mode something like x = 1 will cause an error without the keywords var, let, or const before it.

Also let and const are keywords for declaring block-scoped variables and constants respectively, so we can’t accidentally reference it outside a block.

For example, with var if we write the following code:

if (true) {
  var x = 1;
}
console.log(x);

We’ll see 1 logged from the console.log since it’s not block scoped.

On the other hand, if we use let instead of var:

if (true) {
  let x = 1;
}
console.log(x);

Then we get the error ‘Uncaught ReferenceError: x is not defined.’

As we can see, we can’t reference things in places that we don’t expect.

An alternative way would be to wrap the stuff we want to be private in a function.

For example, we can write:

(function() {
  var x = 1;
})();

console.log(x);

We will also get the error ‘Uncaught ReferenceError: x is not defined.’ A function that runs immediately after it’s declared as we have above is called an Immediately Invoked Function Expression or IIFE for short.

If we want to expose something to the outside in the IIFE we have above we can just return what we want as follows:

let foo = (function() {
  var x = 1;
  return {
    bar: 2
  }
})();
console.log(foo.bar);

We returned an object with the bar property and assigned it to foo. Then we should get 2 from the console.log output.

Photo by Mohau Mannathoko on Unsplash

Keep a Strict Coding Style

Every developer in the team will have their own style if they decide how to style the code.

This means that the code will have different styles in different places, making the code hard to read.

Because of that, it’s a good idea to keep the style consistent. We can style our code automatically with programs like ESLint or JSLint, which does static checks on our code to make sure that it sticks to the style that’s set.

There’re also tools like Prettier to format the code in a consistent way through our codebase.

Clean code is easy to read and maintain. It shouldn’t have hacky things that make it hard to read and debug.

Comment When Needed

While lots of code are self-explanatory, some code needs to be clarified. For example, if the code is part of a complex system, then it might need some clarification with comments.

A simple function that’s a few lines long probably don’t need much explanation.

If we write comments, we should use multi-line comments /* */ instead of single-line comments // since they’re more versatile.

One handy trick for comments is to write it with the double slashes before closing the multi-line comments as follows:

/*
  function foo(){
    return 1
  };
// */

This way, we can uncomment the code by putting a slash before the open slash in the first line to uncomment the code:

//*
  function foo(){
    return 1
  };
// */

The code above is uncommented.

Many text editors should also be smart enough to comment and uncomment JavaScript code automatically.

Variable and functions should be named in a way that indicates what they store or do respectively. Classes should start with a capital letter in general and they should be named for the kind of object that they instantiate.

We should avoid global variables since they can be referenced accidentally and cause unintentional modification. We can keep things private inside functions or modules.

To make code easy to read. It’s important to keep a strict coding style so that we don’t get any confusion when reading code.

Finally, we can comment on code in moderation if there’re parts that are harder to understand.