Optimizing Your JavaScript for Speed
Tags: javascript, webdev, architecture
Published: 2019-06-18 03:42:10

There are often different ways of doing the same thing in JavaScript. You shouldn't waste your time worrying about premature optimizations but there are plenty of times performance does matter. When you are dealing with with huge datasets and lots of DOM elements you can push the browser to it's limits.

There are several questions I've had and I decided to explore them.

Its important to note that these benchmarks are not scientific. They were put together out of curiosity and there are many circumstances that could affect these results. The results I discuss below took place on Chrome's V8 JavaScript engine.

Lets look at some common ways of doing things and see how the browser reacts.

# Concat vs. Spread

When you want to combine arrays you have a few choices. You can use the old style of `arr.concat(arr2)` or you can use the spread operator `[...arr, ...arr2]`. Both of them return a new array.

You might be surprised to find out that for large arrays spread can be about [50% slower](https://jsperf.com/concat-vs-spreader). I found that concat was consistently faster unless the array was less than 10 items.


# Bind vs. Arrow Function

When you pass a callback there are many times you want to preserve your reference to `this`. You have two choices for how to do this. You can do `this.myFunction.bind(this)` or `() => this.myFunction()`. It turns out that using an arrow function is about [83% slower than bind()](https://jsperf.com/bind-vs-array). 

That is, unless if you are calling the function multiple times. It is more expensive to set up the function with `bind()` than it is with an arrow function. So if you are only calling the function once [bind is about 90% slower](https://jsperf.com/bind-vs-array-single).

# Filtering for True

It is a common task to get the truthy values out of an array. There are a few ways to do this. The common ones involve passing something to filter. For some reason filter requires a value. 

So should you cast it to a boolean?
```
arr.filter(Boolean)
```

Just return the value:
```
arr.filter((i)=> i);
```

Or cast it to a boolean using a double negative?
```
arr.filter((i)=> !!i);
```

Its a minor difference but using `arr.filter(Boolean)` is about [9% slower](https://jsperf.com/filter-true) and the no-op arrow function is the fastest. The double negation is about 2% slower and in effect does nothing.

# Sets vs Arrays

Sets and Arrays can be used for a lot of the same things. The main difference is that sets are unique and arrays aren't. The other big differnce is that it is way faster to check if an object exists in a set rather than an array. The difference is off the charts. With 10,000 items JSPref reports `Array.includes` is [100% slower](https://jsperf.com/set-vs-array-contains) than `Set.has`.

But what if you have an Array and you want to check if things exist in it. Should you convert it to a set? Well it turns out creating a set is somewhat expensive. If you needed to check if a 10,000 item Array contained something 200 times [you would still be better off](https://jsperf.com/convert-array-or-check-includes) keeping it as an Array and using `Array.includes` rather than converting it to a set and using `Set.has`. There is an inflection point though. It seems to be right around 400 checks on an array of 10,000 items.

I hope you enjoyed these benchmarks. As always, you should benchmark your usecase and unless your code needs to be highly optimized the most important thing is how the code looks.