Don’t SPREAD the word

With spread power comes great responsibility

The FE programmers are excited, sharing how they are glad about the new option to “spread” in JS6. Most of them even copy the same examples, showing again and again how you merge, cope and spread object. I’m obligated to share that seeing the spread option for the first time, swirled my stomach, and not in a good way.

Let’s start with the good parts, and they are more than wonderful, and sometimes even game changers:

Copy Arrays:

In addition to the four ways to clone an array: loop, slice, Array.from() & concat. JavaScript spread provides one more, slower of them all:

let arrA = [1,2];
let arrB = [...arrA];

arrB.push(3);

console.log(arrA);// ==> [1,2]
console.log(arrB);// ==> [1,2,3]

Join arrays:

In addition to loops & concat…

let arrC = [...arrA,...arrB];
var arrD = [1, 2, arrC, 5, 6] => [1,2,1,2,1,2,3,5,6]

Clone Object:

let objA = {a:'1',b:2};
let objB = { ...objA };

objB.c = 3;
objA.c == undefined;

merge objects:

let objA = { a: 1 };
let objB = { b: 2 };

let objC = {...objA,...objB};
console.log(objC); // ==> {a:1,b:2}

Replace Apply function:

function joinThree(x, y, z) {
   return x + y + z;
}

const arr = ['a', 'b', 'b'];
joinThree.apply(null,arr) == joinThree(...arr);

Pass an unknown number of arguments:

function add(...numbers) {
   return numbers.reduce((sum, next) => sum + next);
}
add(1, 2, 3); // ==> 6
add(1, 2, 3, 4, 5);// ==> 15
let arr = [1,2,3,4,5,6,7];
add(..arr);// ==> 28

But…

And here comes my fear, maybe since I had seen too many coding horrors, or maybe I have seen too many products that had got out of control.

function doIt(operation, ...items){
   const operationsList = {
      'add': (...items) => { // do one thing
      'join': (...items) => { // do somwthing else
   }
   return operationsList[operation](items);
}
doIt('add',1,2,3);
doIt('add',1,2,3,4,5,6);
doIt('join',1);

Nice, isn’t it? Nope, this is a coding horror that points out poor understanding of how to write clean and readable code. And unfortunately, a very common practice at FE developers. If there is a distinction between the first variable and the other, you need to distinguish them as different objects.

function doIt(operation, items){ 
   ...
   ...
   ...

let values = [1,2,3];
doIt('add',values);
doIt('add',[1,2,3,4,5]);
doIt('join',values);

This code is readable, cleaner, safer and I can go on and on.

The same principle, of “the good magic of spread”, comes in many versions:

function formatHonor(firstName, lastName, ...titles){
   return "Ser " + firstName + " " + lastName + " is known as " + titles.join(', ');
}
formatHonor('k','kr','fed','cat'); // ==> Ser k kk is known as fed, cat

The only good use of spread I can think of is if there are no signification or differences between the values, Like at SUM, MAM. If you find yourself addressing one of the specific locations, either as values before the spread (ex  #1) or by location within the array (ex #2), your data structure is wrong.

//ex #1
function(a,b,...c){ 
// If the first two are diffrent than all the rest, 
// seperate tham, so the caller will know that.

//ex #2
function(...c){
   if(c[1]){
   // If the second place is so important, trate it that way

Some believe that less code is better code, but there is nothing more harmfull to a product than dark magic.  And it’s better to have a longer code, but stupid safe, than one clever trick that will fall on the first change. Use it, but use it wisely and clearly.

One more small but annoying thing about the spread syntax, you can no longer place three dots as pseudo code inside JavaScript, knowing that the shift to pseudo is clear… 😉