JavaScript Best Practices

JavaScript Best Practices — Functions and Mutations

Spread the love

Like any kind of apps, JavaScript apps also have to be written well. Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some best practices for working with arrow functions. Also, we look at why and how to avoid mutations.

Don’t Use Getters and Setters

Since getters and setters introduce side effects, we shouldn’t use them if we want to make functions that are easy to work with.

For instance, we shouldn’t write:

const person = {
  name: 'james',
  get age() {
    return this._age;
  set age(n) {
    if (n < 0) {
      this._age = 0;
    } else if (n > 200) {
      this._age = 200;
    } else {
      this._age = n;

Also, we should call __defineGetter__ or __defineSetter__ :

person.__defineGetter__('name', () => {
  return || 'james';


person.__defineSetter__('name', (name) => { = name.trim();

Instead, we create pure functions:

const restrictAge = (n, min, max) => {
  if (n <= min) {
    return min;
  if (n >= max) {
    return max;
  return n;

const setAge = (age, person) => {
  return Object.assign({}, person, { age: restrictAge(age, 0, 120 )});

This way, we have all pure functions, and it’s more versatile than our setter implementation since we can change the min and max .

Reduce the Use of Loops

Most loops in JavaScript code can be rewritten with array methods.

This is because there are already many methods like map , filter , and reduce methods that can let us work with arrays in a shorter way.

Therefore, instead of writing:

for (const a of arr) {
  result.push(a * 10);

We can write:

const result = => a  * 10);

It’s much easier to use map then a for-of loop.

Don’t Use Object.assign with a Variable as the First Argument

Object.assign mutates the first argument.

Therefore, to use it in a way that doesn’t mutate existing data, we should pass in an empty object as the first argument.

Instead of writing:

const a = { foo: 1, bar: 2 };
const b = { baz: 3 };

Object.assign(a, b);

we write:

const c = Object.assign({}, a, b);

Reduce the Use of Mutating Array Methods

Since we have the spread operator and alternative array methods, we can avoid the use of mutating array methods in our code.

For example, instead of writing:


We can write:

const arr = arr.slice(0, arr.length - 1);

The only one that’s harder to replace is sort . In this case, we can make a copy of it with the spread operator and then call sort on that array.

So we can write:

const copy = [...arr];

Instead of splice , we may consider using filter or slice .

If we want to remove one element with the given index, we can write:

const removed = arr.filter((a, i) => i !== index);

Then we remove the item at index index and assigned it to a new variable.

Reduce the Use of Mutating Operators

It’s easy to mutate data accidentally.

So we may want to avoid using mutating operators.

For instance, we may want to avoid using the += , /= , -= , %= or *= operators.

Instead, we can use non-mutating array methods or assigning values to a new variable.

We can write:

const b = a + 10;

instead of:

a += 10;

If we have to do update a variable with new values by adding repeatedly, we can use reduce :

const total = arr.reduce((total, a) => total + a, 0);

Before Careful with null or undefined

We should always be careful with null or undefined values since they are a source of many errors.

Therefore, we should make sure a variable or property isn’t null or undefined before working with them.

To check both, we can write:

if (val === null || val === undefined){


if (val === null || typeof val === 'undefined'){


We should avoid mutating data so that we won’t accidentally change them.

It’s also easier to test function that doesn’t mutate data.

Also, we should be careful of null or undefined .

By John Au-Yeung

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

Leave a Reply

Your email address will not be published. Required fields are marked *