2018.05.31 by Nahuel Scotti | 3 min read

How to make your Javascript code run faster

This article was originally written for dev.to

formula one car

A long time ago, in 2011, I wrote my first DNI (Spanish ID) validation script. I did it with ActionScript. Some years later, after the Flash era, I re-wrote it for Javascript.

Recently, I went into a heavily Functional Programming learning process and as a goal, I propose myself to create a new module applying what I've learned.

The result was: Better DNI

The fastest

Quickly I found out that there were many modules doing the same... So, replicate what others already did was a little boring. I changed my goal to "Create the best and fastest module to validate a DNI".

In the process, I found many ways to improve the speed of my code, although sometimes may looked a bit uglier, it made the code twice faster.

You may get even better results with newer versions of Node/JavasScript.


str.substr() vs str.slice()

"0123456789".slice(-9); // => '123456789'
"0123456789".substr(-9); // => '123456789'

Winner: slice / x21 faster! / perf test

toLowerCase() vs toUpperCase()

I have to admit, I've never thought before why would one method be faster than the other, but here I was. Looking into the V8 code I found that https://github.com/v8/v8/blob/master/src/string-case.cc#L16 was probably the answer to that.

"A".toLowerCase(); // => 'a'
"a".toUpperCase(); // => 'A'

This is especially useful if you need to compare two strings. Before comparing them, it is better to convert them to lower case.

Winner: toLowerCase / slightly faster / perf test

indexOf() vs object[prop]

const y = "xyz".indexOf("y"); // => 1
const y = { x: 0, y: 1, z: 2 }["y"]; // => 1

Winner: indexOf / slightly faster / perf test

String concatenation vs Template literals

I don’t know why I imagined that template literals were more complex than a simple string concatenation.

const x = "x";

"yyy" + x;
// vs
`yyy${x}`; // faster!

Winner: Template literals / slightly faster / perf test

Convert to number

parseInt("1234", 10); // => 1234
// vs
+"1234"; // => 1234

Winner: +sign / x6.12 faster! / perf test

Math.floor() vs Bitwise shift

I took some inspiration from this blog post.

Math.floor(1.123456789); // => 1
// vs
1.123456789 << 0; // => 1

Winner: Bitwise shift / slightly faster in jsperf but Math.floor() performs better much better in my MacBook Pro. / perf test

Useful code optimization tips

Tip 1: Easy validation first

Do easy validations first, and return as quickly as possible:

if (someComplexValidation(value) && value.length !== 9) return;
// vs
if (value.length !== 9 && someComplexValidation(value)) return;

It’s the same code right? Do the “easy” validation first so your code does not run and return if the first validation does not pass.

Tip 2: Avoid costly methods

Avoid using costly methods like toUpperCase() and try to use smart alternatives:

const n = "XYZ".indexOf("y".toUpperCase()); // => 2
// vs
const n = "XYZxyz".indexOf("y") % 3; // => 2

Tip 3: Try multiple approaches

If you know that you can achieve the same result with different methods, find the one that works better for each specific case:

const x1 = "xyz".substr(0, 1); // => 'x'
const x2 = "xyz"[0]; // => 'x'
const x3 = "xyz".slice(0, 1); // => 'x'

I hope this would help you to optimize your code!

Do you want to contribute, make it faster? Open a pull request: singuerinc/better-dni

  • #functional
  • #javascript
  • #optimization