JavaScript Best Practices: More Things to Avoid
Tags: codequality, webdev, programming, javascript
Published: 2021-01-27 00:00:22

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

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, so 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 more constructs that we should avoid, including the misuse of the `for...in` loop, the `==` operator, the `arguments` object, and `this`.

* * *

### Misusing the For…in Loop

The `for...in` loop shouldn’t be used to iterate through arrays and array-like objects. For example, if we have:

```
const arr = ['a', 'b', 'c', 'd', 'e'];
for (let i in arr) {
  console.log(i)
}
```

We get back:

```
0
1
2
3
4
```

However, this is a misuse of the `for...in` loop since it’s supposed to iterate through the enumerable properties of an object and its prototype rather than looping through the indexes of an array.

The order of the enumeration isn’t guaranteed, so we might not loop through the array in order, which is bad.

The `for...in` loop also loops through inherited properties that are enumerable, which is another problem.

For example, if we have:

Then we create an object with a prototype object with the `foo` property. The `for...in` loop will loop through both the enumerable properties of `obj`’s prototype and `obj`.

To avoid looping through the properties of its prototype, we can use `Object.keys` instead:

```
for (let prop of Object.keys(obj)) {
  console.log(prop);
}
```

We can loop through the key-value pair of `obj` without anything from its prototype, we can use `Object.entries`:

```
for (let entry of Object.entries(obj)) {
  console.log(entry);
}
```

For looping through arrays and array-like objects, we should use the `for...of` loop instead:

```
const arr = ['a', 'b', 'c', 'd', 'e'];
for (let a of arr) {
  console.log(a)
}
```

Then we get the entries of the array.

* * *

### Messing With this

The `this` object is always a problem in JavaScript. This is because it changes depending on the scope.

Fortunately, in ES6, we have arrow functions that don’t change the value of `this` if we reference it inside. This also means that we can’t change the value of `this` with `call`, `bind`, or `apply`.

For example, the following code will log the `window` object:

The value of `this` doesn’t change even if we try to change it with `bind`.

Also, ES6 has the class syntax for creating constructor functions so it’s clear that `this` should be inside the class as long as we use class methods and arrow functions.

Class methods will have the class as the value of `this` and arrow functions inside the class will have the same value for `this`.

![](https://cdn-images-1.medium.com/max/800/0*nQrKY-jv3ocT9AWl)Photo by [Casey Allen](https://unsplash.com/@westbeach013?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

* * *

### The == Operator

The `==` operator does automatic type conversion before comparing the operands for equality. This creates issues with different types of data being considered the same.

For example, `null == undefined` returns `true`, which we probably don’t want.

`null == undefined` returns `true` because they’re both falsy.

To avoid these kinds of issues, we should use the `===` operator instead, which would avoid comparisons of these kinds of operands returning `true`. This is because `===` checks the type of each operand in addition to the operand’s contents.

* * *

### The arguments Object

With the introduction of the rest operator, we can finally avoid the use of the `arguments` object for getting the arguments that were passed into a function.

The `arguments` object shouldn't be used for a few reasons. One is that it’s an array-like object, which means properties like `length` are in it and it can be looped through with a `for` loop, but array methods like `map` and `forEach` aren’t included in it.

Also, we can access its entries with its index, which is deceiving since it’s not actually an array.

Using `arguments` also prevents any code optimization by browser engines, which means performance is slower. Also, the `arguments` object isn’t available in arrow functions.

Therefore, to access extra arguments that are beyond the parameters listed, we should use the rest operator instead.

For example, instead of writing:

We can write:

```
const add = (...args) => args.reduce((a, b) => a + b, 0);
console.log(add(1, 2, 3, 4, 5));
```

Notice that it’s much shorter to use the rest operator, which is the `...args` part of the function signature. `args` is already an array so we have all the array methods available for us to use.

* * *

### Conclusion

In modern JavaScript, we can abandon a lot of older constructs to make our code easier to read and maintain.

We can use the rest operator instead of the `arguments` object. This is because the rest operator gives us an array of arguments instead of the array-like `arguments` object.

Also, we should avoid the `==` operator for equality comparison since it does automatic type conversion before comparing which we might not want.

We should also avoid messing with `this` by using arrow functions and class syntax for constructor functions. These two constructs make the value of `this` a lot clearer. We only use class methods for classes and arrow functions for functions that aren’t a method of a class.

Finally, the `for...in` loop shouldn’t be used for looping through arrays and array-like objects since the order of enumeration isn’t guaranteed to be in order, leading to unexpected results.