Categories
JavaScript Best Practices

JavaScript Best Practices for Writing More Robust Code — More About Functions

Spread the love

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 good function features that JavaScript has that we should use.

Destructuring Arguments

Destructuring arguments should be used to take parts of an argument and reference that. This way, we can reference a part of an argument as a variable rather than having to use the path of the property or array to access it.

Also, there are much fewer chances for errors since some properties may be non-existent, null , or undefined , and they’ll throw errors if we access them with the path.

We don’t have to worry about that since we can set default values for properties with the destructuring syntax.

For instance, we can do that with the rest operator and arrays as follows:

const f = (a, b, ...[d, e]) => {
  console.log(d, e);
}

Then when we call it as follows:

f(1, 2, 3, 4, 5);

We get that d is 3 and e is 4.

Also, we can use the destructuring syntax on object arguments. For instance, we can write the following code to use that:

const f = ({
  foo: {
    bar
  }
}) => {
  console.log(bar);
}

In the code above, we have the following function signature:

({
  foo: {
    bar
  }
})

This code takes the foo.bar property’s value and assigns it to the bar variable.

Then when we call it as follows:

f({
  foo: {
    bar: 1
  }
});

We get that bar in f is 1.

The good thing about the destructuring syntax is that it won’t throw errors when we try to destructure a property that doesn’t exist if we set default values for them

For instance, if we have the following function:

const f = ({
  foo: {
    bar
  } = {}
}) => {
  console.log(bar);
}

Then when we call it as follows:

f({});

We’ll get undefined instead of an error since we set the foo property to an empty object.

Likewise, we can set default values for destructured array entries as we wish. For instance, we can write:

const f = (a, b, ...[d, e = 4]) => {
  console.log(d, e);
}

Then we call it as follows:

f(1, 25);

We get that d is undefined and e is 4 since we set e ‘s default value to 4.

As we can see, there’s less chance for committing errors and also it’s clearer since we can see the structure of the arguments.

Minimize the Use of Traditional Functions

The use of traditional functions should be minimized. Not only we need to type the function keyword every time.

Also, with traditional functions, we have to worry about the value of this and arguments . We also have to think if it’s hoisted or not.

Hoisted functions, which are function declarations, can be referenced anywhere in a script, but function expressions can’t be referenced until they’re defined.

Moreover, we don’t have to worry about how to call , bind , and apply if we don’t use traditional functions.

These things are always confusing.

With the class syntax for constructor functions, there’s also no reason to use them to create constructor functions.

This is because the class syntax tells us when we have errors in our class declarations.

For instance, if we have the following JavaScript class hierarchy:

class Foo {
  constructor(foo) {
    this.foo = foo;
  }
}
class Bar extends Foo {
  constructor(foo) {
    super(foo);
  }
}
const bar = new Bar();

Then when we forgot to call super in the constructor of Bar , we’ll get an error since we have constructor in the Foo class that takes an argument.

We want these errors to be shown so we can fix them before the code goes to production.

This is in contrast to what we have before we have the class syntax:

function Foo(foo){
  this.foo = foo;
}

function Bar(foo){
  Foo.call(this, foo);
}

Bar.prototype.constructor = Foo;
const bar = new Bar('foo')

This does the same thing as the class syntax, but we get no errors if we miss the call and constructor .

Conclusion

We should use the destructuring syntax so that we can see the structure of our arguments more clearly and selectively use parts of the arguments in our functions.

Also, we shouldn’t use traditional functions anymore in most cases since they are more confusing and complex and harder to understand.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published.