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 learned.
The result (not following FP paradigm too much I would say) is:
singuerinc/better-dni_better-dni - The fastest Spanish DNI (NIE / NIF) validation_github.com
Quickly I found out that there are many modules doing the same…
Replicate what others already did is a little boring, so I changed my goal to
“Create the faster module to validate a DNI”
In this process, I found many ways to improve the speed of the code, although sometimes it looks a bit uglier, some of them made the code twice faster.
Note that you might get different results based on browser+cpu+etc. My findings are based basically on Chrome/Node. I would say that you should test your code in different environments and see where you can optimize.
Here is what I discovered:
'0123456789'.slice(-9); // => '123456789''0123456789'.substr(-9); // => '123456789'
Winner: slice / x21 faster! / test
I have to admit that I have never thought before why would one method be faster than the other. I was looking into the V8 code and looks like https://github.com/v8/v8/blob/master/src/string-case.cc#L16 is the answer to that.
'A'.toLowerCase(); // => 'a'
'a'.toUpperCase(); // => 'A'
This is especially useful if you need to compare two strings.
Before comparing them, better to convert them to lower case.
Winner: toLowerCase / slightly faster / test
Random image related to speed. You need one in all posts. Photo by James Traf on Unsplash
const y = 'xyz'.indexOf('y'); // => 1
const y = {x: 0, y: 1, z: 2}['y'] // => 1
Winner: indexOf / slightly faster / test
I don’t know why I imagined that template literals were more complex than a simple string concatenation.
const x = 'x';
'yyy' + x;
`yyy${x}`; // faster
Winner: Template literals / slightly faster / test
parseInt('1234', 10); // => 1234
+'1234'; // => 1234
Winner: +sign / x6.12 faster! / test
I took some inspiration from this blog post.
Math.floor(1.123456789); // => 1
1.123456789 << 0; // => 1
Winner: Bitwise shift / slightly faster in jsperf but Math.floor() performs much better in my MacBook Pro. / test
Do easy validations first and return as quickly as possible. Take a look at these snippets:
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.
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
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_better-dni - The fastest Spanish DNI (NIE / NIF) validation_github.com