Same problem, different solutions

Well, a while back, it would have been very common to see something along these lines for the following problem:

Given an array of unordered numbers, return a new array adding 1 to each value and sorting it without mutating the original

var numbers = [2, 4, 12, 6, 8, 29, 5, 10, 87, 11, 7];



function process(arr) {

let newArr = arr.slice();

newArr[0]++;

for (let i = 1; i < newArr.length; i++) {

const current = newArr[i] + 1;

let leftIndex = i - 1;



while (leftIndex >= 0 && newArr[leftIndex] > current) {

newArr[leftIndex + 1] = newArr[leftIndex];

leftIndex = leftIndex - 1;

}

newArr[leftIndex + 1] = current;

}

return newArr;

}



const newArray = process(numbers);

(I’m using insertion sort, just because it was easier to implement)

This code sample is not really readable but yet, is performant, way more performant than a readable ES6 code, for example, this one:

const process = (arr) => arr

.map(num => num + 1)

.sort((a, b) => a - b);



const newArray = process(numbers);

As a matter of fact, the first code sample is ~75% faster than the second one, even though the second one is more readable and could even be simplified into a one-liner:

const newArray = numbers.map(num => num + 1).sort((a, b) => a - b);

Or split with helper functions for better readability:

const addOne = (n) => n + 1;

const asc = (a, b) => a - b;

const newArray = numbers.map(addOne).sort(asc);

It’s obvious that the ES6 sample (whatever approach) is way more readable making the code easier to understand at a glance. With a readable code we can introduce new developers to projects way faster, we can share our code easier and it becomes more maintainable.

All things considered, performance becomes dispensable in most cases. That’s why ES6 evolved this way.

Final comparison between both approaches:

At this point, you’ll probably be asking yourself: “What else is less performant but more readable?”

Well, let’s have a look at some of the main use cases together.

Spread syntax vs Object.assign()

Take the following simple problem:

Copy an object and add a new property to the copy

Solutions:

const params = {...}; // filled Object



// ES6 - Spread syntax

var copy1 = { a: 2, ...params };



// Object.assign()

var copy2 = Object.assign({}, { a: 2 }, params);

Both these approaches do the job, but we can all agree that spread syntax is way more readable even though is ~54% slower.

For loop vs Reduce

Problem:

Sum all the values of an array

Solutions, let’s start with the classic for…loop:

const numbers = [2, 4, 12, 6, 8, 29, 5, 10, 87, 11, 7];



function arraySum(arr) {

let sum = 0;

for (let i = 0; i < arr.length; i++) {

sum += arr[i]

}

return sum;

}



const sumOfNumbers = arraySum(numbers);

Let’s now go for the all mighty reduce:

const numbers = [2, 4, 12, 6, 8, 29, 5, 10, 87, 11, 7];



const add = (a, b) => a + b;

const arraySum = (arr) => arr.reduce(add);



const sumOfNumbers = arraySum(numbers);

In this case, reduce is extremely expensive from a performance point of view, is ~96% slower!

For vs While vs Do while

The difference is almost unnoticeable but, nonetheless, in case of doubt… Go with the classic for loop.