Categories
JavaScript Best Practices

JavaScript Best Practices — More Code That Shouldn’t be Added

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at more code that shouldn’t be added to our JavaScript code.

No Implicit Global Variable Declaration

A global variable declaration can be done in various ways in JavaScript. Without strict mode enabled, we can declare a global variable with var .

For instance, we can write something like the following to create global variables without strict mode:

var x = 1;

Since the code above is in the top level, if we have strict mode off, we’ll declare a variable in the global scope.

In the browser, the code above is the same as window.x = 1 .

Therefore, using var isn’t the best way to declare a variable at the top level without strict mode.

Now that we have let and const , we should use those instead since they won’t declare a global scope, and also, their scope is consistent anywhere. They always declare variables in a block scope.

Even in the top-level, they won’t declare global variables. Preventing declaring global variables accidentally can also be done with enabling strict mode.

This way, the example we have above won’t attach x as a property of window .

No Implied eval() Code

setTimeout and setInterval can accept a string that runs the code as a their callback.

For instance, the following:

setTimeout("console.log('foo');", 100);

does the same thing as:

setTimeout(() => console.log('foo'), 100);

setInterval has the same feature, so:

setInterval("console.log('foo');", 1000);

does the same thing as:

setInterval(() => console.log('foo'), 1000);

This means that we can insert any string into either function and run the code.

The string is interpreted in the global scope, so anybody can set variables inside themselves if they wish and run arbitrary code. Running code from a string is also slower. Therefore, we should avoid passing strings into setInterval and setTimeout .

Instead, we should pass in a callback.

No this Keywords Outside of Classes or Class-Like Objects

The keyword this shouldn’t be used where it isn’t needed. Therefore, it shouldn’t be used outside of constructor functions, object literals or classes.

Object literals can have this inside its methods. Getters and setters inside objects, constructor functions, and classes can also reference this since they’re part of an instance.

this can also be referenced in callbacks and traditional functions that calls call , apply , or bind .

For instance, we can write the following code:

function() {
  this.foo = 0;
}

The following is also good:

class Foo {
  constructor(foo) {
    this.foo = foo;
  }
}

Things like arrow functions should have this in it, since it doesn’t bind to this , so:

() => this.foo;

isn’t proper JavaScript code.

We can also use call as follows:

(function foo() {
  console.log(this.foo)
}).call({
  foo: 'bar'
})

Then we see that the console log outputs 'bar' , which is the valur of foo that we pass into call .

Photo by Kevin Mueller on Unsplash

Disallow Iterator

The __iterator__ property was a custom property of an object’s prototype that’s used to create a custom iterator for for...in loops.

Now that JavaScript has iterators, we don’t need this. For instance, the following is now obsolete code:

Bar.prototype.__iterator__ = function() {
    return new BarIterator(this);
}

We shouldn’t write code like that anymore now.

Disallow Labeled Statements

We can add labels to JavaScript in conjunction with break and continue to control the flow of multiple loops.

For instance, if we have:

outer:
  for (let i = 0; i < 5; i++) {
    while (true) {
      break outer;
    }
  }

Then we end the for loop when the while loop is first executed. The better way to use break and continue is without labels.

The code above is more error-prone and harder to understand than the code without labels.

For instance, we should write:

while (true) {
  break;
}

so we don’t have labels.

Conclusion

A global variable declaration shouldn’t be added accidentally to our JavaScript code. To do this, we should make sure strict mode is on and we aren’t using var if it’s off.

We can pass in a string to setTimeout and setInterval to run code. They’re all run in the global scope. This lets anyone sets global variables and run code as they wish. Also, it’s slower than running the actual code. Therefore, we shouldn’t use strings as callbacks in those functions.

this should only be included when it’s needed. They’re needed only in constructor functions, classes, and object methods.

The __iterator__ is obsolete and shouldn’t be used. Finally, labels are also not commonly used for marking loops for reference and shouldn’t bee used since it’s error-prone and hard to read.

Categories
JavaScript Best Practices

JavaScript Best Practices — Error Processing and Exceptions

JavaScript is a very forgiving language. It’s easy to write code that runs but has issues in it.

In this article, we’ll look at how to handle errors in JavaScript programs.

Design Implications of Error Processing

If we handle errors in our system, then we got to test our error processing code.

This is to ensure that we did everything properly.

If we have return values, then we test the return values.

We should never ignore error information.

If we have a consistent approach for handling errors, then we should follow it so that we can have issues with inconsistency and duplication of error processing code.

Exceptions

Exceptions are the means of which code can pass along errors from the code that caused the error to the surface.

If we don’t want our program to crash, then we should catch them so that we can deal with them gracefully.

In JavaScript, we can throw errors by using the throw keyword on the Error class or subclass of Error .

To catch errors, we can use try...catch to catch them.

If we want to run code regardless of whether an exception is thrown, we can put them in the finally clause.

For instance, we can write the following to throw an error:

throw new Error('error');

To catch exceptions that are raised from code that may cause errors, we write:

try {  
  errorThrowingCode();  
  //...  
} catch (ex) {  
  // handdle errors  
}

Where errorThrowingCode may throw errors.

A finally clause may be added after the catch block.

Use Exceptions to Notify Other Parts of the Program About Errors that Should not Be Ignored

The whole point of throwing exceptions is that we can’t ignore them without users seeing them.

Therefore, we should use exceptions to notify other parts of our programs about errors that shouldn’t be ignored.

Throw an Exception Only for Conditions that are Truly Exceptional

Even though we should throw exceptions for things that shouldn’t be ignored, we shouldn’t use them everywhere.

If we have too many then, then we’ve to have code everywhere to handle exceptions.

We don’t want that, so we should think about using exceptions for those errors that must be handled for proper operations of our program.

Exception handling makes our code more complex as we have to catch them and then handle them.

There’re better ways to deal with non-critical errors like checking for values and do something instead of throwing exceptions.

Don’t Use an Exception to Pass the Buck

If errors can be handled locally, then we should do that.

Handling them elsewhere just makes our code more complex.

Include in the Exception Message All Information that Led to the Exception

We should include useful information in our exceptions so that we can have enough information to debug and fix the issue that caused the exception to be raised.

It just makes dealing with errors easier if we give everyone more information so that we can deal with them.

Avoid Empty Catch Blocks

Empty catch blocks are useless, so we shouldn’t include them.

We got to handle exceptions that are thrown rather than doing nothing when an exception is caught.

If we want to do nothing, we should at least log about the error.

Know the Exceptions Our Library Code Throws

Knowing exceptions that our libraries throw is important so that we can handle them when they arise.

Failing to catch them will be caught our program to crash and that won’t be good user experience.

Consider Building a Centralized Exception Reporter

Creating a centralized exception reporter makes logging and formatting exceptions a breeze as all that is done in one place.

It’s better than handling them all separately in different places.

Standardize Our Project’s Use of Exceptions

For the sake of keeping things consistent, we should standardize how exceptions are handled in our code to reduce developers’ cognitive load.

We can create project-specific exception classes and define code that is allowed to throw exceptions.

Also, we can centralize reporting and logging.

Conclusion

There is a lot to think about when we throw exceptions.

We got to think about when and how to throw exceptions. Where they handle and whether we can create our own error classes.

Standardization would make our work easier.

Categories
JavaScript Best Practices

JavaScript Best Practices for Writing More Robust Code — Clean Code

JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust JavaScript code.

In this article, we’ll look at some ways to keep our JavaScript code clean and easy to read so that changing it is a piece of cake.

Keep Code Organized

Our JavaScript code should be organized well so that they can be easily reasoned with. Well organized code don’t repeat anything.

Functions and classes inside all do one thing only and no more. They’re mostly independent of each other, and they only expose what’s needed to the outside world, which is the bare minimum to avoid tight coupling.

This is easy to do if we organize things cleanly from the beginning. For instance, we can write the following code to keep things clean:

fruit.js

export class Fruit {
  constructor(name) {
    this.name = name;
  }
}

person.js

export class Person {
  constructor(name) {
    this.name = name;
  }
}

index.js

import { Fruit } from "./fruit";
import { Person } from "./person";
const sentence = `${new Person("foo").name} likes ${new Fruit("apple").name}`;
console.log(sentence);

In the code above, we have 3 modules. The first 2, person.js and fruit.js all have one class.

They all have one class each and the class only represent one thing. The Person class represents a person and the Fruit class represents a fruit.

Then in index.js , we import both of them and reference them in the string.

With the way we organized the code, the classes don’t reference each other. Each class only does one thing, and we only reference the classes when it’s necessary.

Don’t Write Clever Code

Clever code is bad because they’re usually hard to read, even though they’re usually shorter.

Simple solutions are better for maintenance than clever code. Clever but hard to read code isn’t good since they’re hard to reason with.

For instance, the following code is an example of clever but hard to read code:

const foo = bar ? bar ? qux ? 0 : 1 : 2 : 3;

In the code above, we have a series of nested ternary operators used in one line, which is shorter than writing out each if statement directly, but it’s hard to read.

Many people probably don’t understand what it’s doing. They have to write out the parentheses in their head so that they can where each ternary operation starts and ends.

Therefore, we shouldn’t have nested ternary operators used like that. Instead, we should write use if statements or only use ternary operators to return one thing or the other for one condition.

Debugging is harder than programming, and we often have to revisit old code to debug and make changes. So we shouldn’t make our job even harder by writing clever code that is hard to read.

Photo by Charis Gegelman on Unsplash

Splitting Code in Ways That They Can Be Tested Easily

Our code should be organized in a way that can be tested easily. This means that they should be exposed to the outside so that they can tested with unit tests.

We should also aim to write pure functions. Pure functions always return the same output for a given set of inputs. This means that they can easily be tested.

Side effects should be minimized in functions so that we don’t have to check code that’s outside the function for correctness when we’re testing.

For instance, we can write our code and tests as follows:

math.js

const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
module.exports = { add, subtract };

math.test.js

const { add, subtract } = require('./math');

test('adds 1 + 2 to equal 3', () => {
  expect(add(1, 2)).toBe(3);
});

test('adds 1 - 2 to equal -1', () => {
  expect(subtract(1, 2)).toBe(-1);
});

In the code above, we have math.js with the functions that we want to test. They’re both pure functions so that they always return the same output for the given set of inputs.

Then in math.test.js , we have 2 tests that are run with Jest to test those 2 functions that we imported from our math.js module.

We called add and subtract to test them and check their values with Jests’s built-in expect and toBe methods.

We want to organize our code this way so we can easily expose them for testing.

Also, they have no side effects so that they can be tested on their own without checking results on code that’s outside.

Conclusion

Code organization is important for writing robust JavaScript since it’s harder to break clean code. They shouldn’t be tightly coupled. Also, side effects should be eliminated as much as possible for easy testing and reasoning.

Finally, clever code should be avoided since they’re often hard to read.

Categories
JavaScript Best Practices

JavaScript Best Practices for Writing More Robust Code — Avoiding Bad Code

JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust JavaScript code.

In this article, we’ll look at some bad code that should be avoided if we want to write more robust JavaScript code.

Avoid Large Modules

Large modules are bad because they have too many members, which makes them hard to track and debug.

Longer pieces of code are also hard to read.

Modules should be small. For instance, we can have one module that only does mathematical operations.

We can write something like the following:

export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

The code above is short and easy to read.

Avoid Modules With Multiple Responsibilities

Modules with multiple responsibilities are probably doing too much.

This violates the single responsibility principles which are bad because it’s confusing to have many different things going on in one piece of code.

Modules with multiple responsibilities are confusing for many people since they do too many things. It’s not logical to have one module to be doing more than one thing.

For instance, if we have:

export const add = (a, b) => a + b;
export const foo = () => console.log("foo");

then that’s bad because we have functions in a module that do multiple kinds of things.

We have an add function that adds 2 numbers, and another function that logs 'foo' .

This doesn’t make sense since it does multiple things. This makes using it harder since we’ve to look at it to find out what the module does.

If the module only does one thing and the module name suggests that it’s so, then people don’t have to look too hard to find out what a module is doing.

Avoid Tight Coupling

Tight coupling is bad because it’s easy to break code when we need to change it, which is inevitable.

To avoid tight coupling, we should avoid exposing too many members from a module to the outside.

When 2 modules are tightly coupled, this means that 2 classes have to change together.

On the other hand, loose coupling of modules means that they’re mostly independent.

Other entities that may be tightly coupled include classes and functions. For instance, if we have the following code:

index.js

import { greet } from "./module";
export class Person {
  constructor(name) {
    this.name = name;
  }

  greet(greeting) {
    greet(`${greeting} ${this.name}`);
  }
}

module.js

import { Person } from "./index";
export const greet = greeting =>
  console.log(`${greeting} ${new Person("foo")}`);

In the code above, we have the greet function outside index.js and we imported Person in the greet function. In index.js , we have the Person class that imported the greet function from module.js .

This kind of dependency structure is too tightly coupled because Person depends on greet and greet depends on Person .

When one changes, we’ve to worry if it breaks the other, which isn’t good since it makes our code more fragile and slows us down when we try to make changes.

It’s better for them to be independent. If we don’t need them to be dependent on the other, then we should eliminate that dependency.

For instance, we can write the following:

index.js

class Person {
  constructor(name) {
    this.name = name;
  }

  greet(greeting) {
    console.log(`${greeting} ${this.name}`);
  }
}

module.js

export const greet = greeting => console.log(greeting);

In the code above, we kept them independent by eliminating the imports and referencing of the dependencies.

This is much cleaner and we don’t have to worry about breaking things outside of the code the module the items are in since they don’t depend on each other.

Avoid Magic Numbers

Magic numbers are numbers that occur in multiple places with an unexplained meaning. They’re often used as constants.

Since they’re used as constants, they should be replaced with named constants.

For instance instead of writing the following:

const foo = 1;
const bar = 1;
const baz = 1;

We should use a named constant instead of 1. For instance, we can write the following:

const CONSTANT = 1;
const foo = CONSTANT;
const bar = CONSTANT;
const baz = CONSTANT;

This way, we know that 1 is constant and give it meaning. Constant names in JavaScript are usually upper-case to make it clear that it’s a constant.

Conclusion

To write robust JavaScript, we should create small modules that only does one thing.

Tight coupling between entities should be eliminated. Finally, magic numbers should be avoided and should be replaced with constants.

Categories
JavaScript Best Practices

JavaScript Best Practices for Writing More Robust Code — Error Prevention

JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust JavaScript code.

In this article, we’ll look at ways to write more robust code when dealing with JSON and best practices when writing code to handle errors better and to prevent them from happening.

Use try…catch When Using JSON.parse or JSON.stringify

JSON.parse and JSON.stringify will throw errors if they encounter issues.

Whenever JSON.parse encounters invalid JSON in a string, it’ll throw an error. JSON.stringify throws errors when it tries to convert a circular structure to JSON.

Therefore, we should use try...catch to wrap around JSON.stringify and JSON.parse to prevent errors from stopping our program from running.

For instance, we should write something like:

try {  
  const json = '{}';  
  const parsed = JSON.parse(json);  
} catch (ex) {  
  console.error(ex);  
}

so that JSON.parse won’t crash our program when it runs into issues parsing JSON. We can also replace JSON.parse with JSON.stringify for code that uses that.

Use ESLint or Another Linter to Catching Errors Early

ESLint is a standard linter for JavaScript. It checks for syntax errors and confusing code to prevent developers from committing many kinds of problematic code or potential bugs.

It has a big list of rules which check for possible errors or useless and confusing code.

For instance, it checks for return statements in getters. This because there’s no point in having a getter that doesn’t return anything in a JavaScript or class. A getter that returns nothing is useless and it’s probably a mistake if it’s there.

Other things include disallowing the assignment operator in conditional expressions, as we probably want to use == or === to compare things instead and we forgot the extra equal sign.

There’re many more rules located at https://eslint.org/docs/rules/.

It’s easy to set up for any project. We can just install eslint in our project folder by running:

npm install eslint --save-dev

Then we create ESLint configuration file by running:

npx eslint --init

to customize the rules that we want to enable. It’s very flexible and we don’t have to enable checks for all the rules.

It also has lots of plugins to add more rules. Popular rules include Airbnb and the default rules. We can also include Node.js rules, Angular, React, Vue, etc.

Don’t Mess With Built-in Object Prototypes

We should never mess with prototypes of built-in global objects. Objects like Object , String , Date , etc. all have instances methods and variables in their prototypes which shouldn’t be messed with.

If we change them by mistake, then our code probably won’t work the way we expect them to since they often call instance methods from these built-in objects and manipulating them in our code will probably break our code.

The member of native objects may also have name collisions with members in our own code.

It’s also confusing since if we change the built-in object’s prototypes, a lot of people may think that it’s actually a method that’s part of the standard library.

We don’t want people to make that mistake and write more bad code and create more issues down the road.

Therefore, we should never modify built-in objects and their prototypes.

If we need any new functionality that built-in native objects don’t provide, then we should write our own code from scratch and reference built-in native items if necessary.

Also, if we want to use new native methods that don’t exist in the browser your app is targeting, then we can use polyfills to add that functionality instead of implementing it from scratch ourselves.

Photo by Sean McGee on Unsplash

Always Use Strict Mode

JavaScript used to let people do a lot of things that people aren’t supposed to do.

Strict mode throws errors when we write code that isn’t supposed to be written, like assign null or undefined with a value, or accidentally creating global variables by omitting var , let or const .

Other things that throw errors include trying to extend objects new properties that have the Object.freeze method applied to it.

For instance, the following will do nothing without strict mode:

const foo = {};  
Object.preventExtensions(foo);  
foo.newProp = 'foo';

However, with strict mode on:

'use strict'  
const foo = {};  
Object.preventExtensions(foo);  
foo.newProp = 'foo';

We’ll get an error ‘Uncaught TypeError: Cannot add property newProp, object is not extensible’.

It also prohibits us from using keywords and constructs that may be used in future versions of JavaScript. For instance, we can’t declare a variable called class since it’s a reserved keyword.

Strict mode is applied to all JavaScript modules by default. However, old-style scripts don’t have strict mode on by default. Therefore, we should make sure that those have strict mode on by adding 'use strict' to the top of our code.

We can also add 'use strict' inside a function, but we definitely want strict mode everywhere so we should just put it on top of the script file.

Since strict mode prevents us from committing so many kinds of errors, we should always have it on.

Conclusion

Preventing JavaScript code errors is easy with ESLint and strict mode. They prevent us from making so many kinds of errors that it’ll save us a lot time from debugging bad code.

Also, we should use try...catch to catch errors when parsing and stringifying JSON.