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.

Categories
JavaScript Best Practices

JavaScript Best Practices: Objects

Like any other programming language, JavaScript has its own list of best practices to make programs easier to read and maintain. There’re lots of tricky parts to JavaScript, so there’re many things to avoid. We can follow some best practices easily to make our JavaScript code easy to read.

In this piece, we look at how to deal with objects in an easily maintainable way. We go through the traps that we can fall into when we define objects.


Use Literals for Primitive Values

In JavaScript, there’re multiple ways to declare primitive variables. Primitive variables include variables of any type other than objects.

One way is to use literals like so:

let x = 1;  
let y = true;  
let z = '';

In the code above, we set the literal value for number, boolean, and string to each variable.

Alternatively, we can write:

let x = new Number(1);  
let y = new Boolean(true);  
let z = new String('');

We can also write:

let x = Number(1);  
let y = Boolean(true);  
let z = String('');

Of the three ways to declare primitive variables above, some ways are better than the others. The best ways are to set the literals directly. The other way is to use the functions as we have in the third example.

Why shouldn’t we use the constructor to create variables with primitive values? First, anything defined with the new operator will have the type ‘object’ even though they have primitive values. This makes comparison between these objects difficult.

For example, if we write:

new String('foo') === new String('foo')

We get false because they’re both of type ‘object’, and === will evaluate to false if two objects don’t have the same reference in JavaScript. This means comparison is difficult.

Comparing with == will also evaluate to false for the same reason.

Since they’re both of type ‘object’, it’s harder to know whether they’re actually strings, booleans, or numbers.

The other two ways are much better because they’ll get us the right type. For example, the following will get us the type ‘number’:

let x = 2;  
console.log(typeof x);

This also applies to other primitive data types.

There’re no reasons to use the new operator to declare things with primitive values. It just makes life harder.

Using new is also slower since the JavaScript interpreter has to do one more operation than necessary to declare something that has a primitive of type ‘object’.

The Number , String and Boolean functions are useful for converting objects from one type to another. For example, if we have:

let x = '2';

Then we can convert it to a number with a Number function as follows:

let y = Number(x);

Use Literals to Declare Objects Whenever They Exist

Some objects have literals associated with them. For example, arrays have the [...] literal. Regular expressions can be declared by surround patterns with slashes. Functions can be declared with the function keyword or using the fat arrow.

It’s confusing to define values with constructors sometimes. For example, arrays have two constructors. One has one parameter with the array length as the parameter. The other is a comma-separated list of entries.

This means that Array(1) will get us an empty array with length 1 and no content. On the other hand, Array(1,2,3) will get us [1,2,3].

As we can see, it’s just not as clear to declare an array by using the constructor.

For functions, we have the function keyword or Function constructor.

Using the Function constructor doesn’t make sense since we have to pass strings that have the code for our functions and strings for the parameter names. It opens things up for code injection attacks, and it’s a pain to write code as a string.

The function keyword is much more clear. And it lets us write code that’s recognized by text editors as function code. There’s no reason to declare a function with the Function constructor unless we want to define a function that has dynamic code.

Likewise, the RegExp constructor is good for constructing regular expression objects dynamically, but otherwise is the same as the regular expression literal. The regular expression literal and constructor are the same for static regular expressions, so there’s some use for the constructor.

The Object constructor just makes us type more code than object literals; otherwise, they’re the same. This means it’s kind of pointless to use it to declare objects.


Automatic Type Conversions

For primitive values, JavaScript can convert things to different types depending on the context.

For example, suppose we have:

1 == '1'

Then the string 1 will be converted to a number.

Suppose we have:

1 + '1'

Then the number 1 will be converted to a string so that we get '11'. JavaScript just assumes that we’re concatenating.

On the other hand, suppose we write:

1 - '1'

We get 0 because it assumes that we’re subtracting two numbers.

Suppose we write:

1 - 'a'

Because the result isn’t a number, we get NaN since we can’t subtract a number with a non-numeric string.

In an expression that evaluates to a boolean, the variables or values inside are evaluated to their truthy or falsy values.

Falsy values include:

  • 0
  • null
  • undefined
  • empty string
  • false
  • NaN

Everything else is truthy. Suppose we have the following:

0 || undefined || null || 1

We get 1. The JavaScript interpreter evaluates all the falsy values and returns 1 since that’s the last thing left.

To make sure we get the types we expect, we should convert everything to the type that we actually expect or we should check for the type.

To convert primitive values like numbers, booleans, and strings, we can use the Number , Boolean , and String functions respectively. We just pass in whatever objects to these functions.

We can also use the + sign before something to convert it to a number.

!! also converts things to boolean according to their truthiness. The first exclamation mark converts the value according to its truthiness and then negates it. Then the second exclamation mark converts it back to the original truthiness value.

To check the type of primitive values, we can use the typeof operator. However, note that null has the type ‘object’. Everything has the type that we expect.


In most cases, object literals are the clearest way to define objects. The only exceptions are when we need functions with dynamically generated code or regular expressions that are dynamically generated. We should never use the new keyword to declare things that have primitive values. Finally, we should be careful of automatic type conversions and check the types or convert them according to our needs.

Categories
JavaScript Best Practices

JavaScript Best Practices — Unexpected Values 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 lots of tricky parts to JavaScript, and there are many things to avoid. We can follow some best practices to make our JavaScript code easy to read.

In this article, we look at the best way to compare objects and function parameters, adding a default value to switch statements and function parameters and avoiding the use of the eval function.

Use === For Comparing Objects

In JavaScript, there are 2 operators for equality comparison. One is the == operator and the other is the === operator. == compares the operands by converting them to the same type automatically.

=== compares by both comparing the content and the type of both operands.

We want to use === because it compares both the type and the content so that we won’t get any mismatch in the type.

For example, if we use the == operator, we can the following expressions evaluated to true :

0 == "";  
0 == null;  
0 == undefined;  
null == undefined;  
1 == "1";

In the first 4 lines, everything is falsy so they’re all converted to false before comparing for equality with the == operator.

In the last line, '1' is converted to 1 before comparison so that we get the value true returned.

To avoid these confusing results, we can use the === operator, which compares both the type and the content of the values. With ===, everything above will be evaluated to false .

If we want to compare things with the same content and different types with the === operator, we can convert them to the same type first.

For example, if we want compare 1 and '1' , we can write:

+1 === +'1'

Then they’ll both be converted to 1 and the expression will evaluate to true.

This way, we don’t get anything with unexpected types being compared.

Default Parameters

JavaScript functions can take in any number of parameters even though they have their own signatures. This means that we can pass in fewer parameters than we expect.

With ES6, we get the default parameter value feature. This lets us set the default value for function parameters.

For example, we can write:

const add = (a, b = 0) => a + b;

Then we don’t have to pass in the second argument for the function to return a numerical value. If we write:

console.log(add(1));

We get 1 since the value of b will be set 0 if nothing is passed, so we get 1 + 0 which is 1.

Photo by Kristina Paparo on Unsplash

Add Default Value for Switch Statements

We should always add a default block to switch statements, since we might have unexpected values being passed into the switch statement.

For example, we should write:

const getDayName = (dayOfWeek) => {  
  let day;  
  switch (dayOfWeek) {  
    case 0:  
      day = "Sunday";  
      break;  
    case 1:  
      day = "Monday";  
      break;  
    case 2:  
      day = "Tuesday";  
      break;  
    case 3:  
      day = "Wednesday";  
      break;  
    case 4:  
      day = "Thursday";  
      break;  
    case 5:  
      day = "Friday";  
      break;  
    case 6:  
      day = "Saturday";  
      break;  
    default:  
      day = "Unknown";  
  }  
  return day;  
}

To get the day of the week, because we can pass in anything to the getDayName function. For example, we can write:

console.log(getDayName(0));  
console.log(getDayName(1));  
console.log(getDayName(1000));

If we pass in 1000, we need to handle that, so we need a default value.

Don’t Use Eval

The eval function accepts a string that contains JavaScript code, which will be run by this function.

We shouldn’t use it because it lets code from unknown sources run, which is a big security risk.

Also, it’s also slower than normal code since it’s interpreted on the fly. This is because the code can’t be optimized by JavaScript engines.

Modern interpreters convert code to machine code, which can’t be done with code passed into eval . This means that the interpreter has to do variable lookups on the fly to set things to the right variables.

Any operations that are done to variables will force the browser to re-evaluate the code again if it’s running code passed into the eval function.

Conclusion

When we compare objects for equality, we should use the === operator since it compares both the content and the type of the object. Also, we should put default values for parameters in case they aren’t passed into the function when it’s called. Also, we should add a default block to switch statements to deal with unexpected values. Finally, don’t use the eval function because it’s a big security that allows people to inject malicious code to our programs and it’s slow to run code with eval .