DEV Community

Cover image for JavaScript spread syntax gotcha
Damilola Emmanuel Olowookere
Damilola Emmanuel Olowookere

Posted on

JavaScript spread syntax gotcha

Well, we all like spreads of all kinds. But this type of spread's got a gotcha.

While it may seem obvious, it really did not occur to me until I traced a bug to it.

Consider a scenario whereby you are keeping a collection of programming/scripting languages. You now defined something like this:

const languages = {
    "interpreted": ['php', 'javascript'],
    "compiled": [
        "java", 
        {"name":"c#","preferred":true},
        "rust"
    ]
}
Enter fullscreen mode Exit fullscreen mode

Now, you've got yourself a beautiful collection of languages. Suppose you want to send Bob your language collection, and you don't want whatever Bob does to his own copy of this language collection to affect yours, how do you do that?

Well, for me, as a JavaScript Senior Dev Super-guru™️ that I am, I will spread the butter on the bread, like this:

const bobsCopyOfLanguages = {...languages};
Enter fullscreen mode Exit fullscreen mode

Well, suppose I know that Bob does not like C#; and I do not want Bob to know about my secret affair with Miss C#, so I smartly and swiftly coded in my lie, like so:

bobsCopyOfLanguages.compiled[1].preferred = false;
Enter fullscreen mode Exit fullscreen mode

Yeah. Done and dusted. Now Bob has a Certified True Copy™️ of my Certificate of non-preference for C#. Cool!

Well, now I've sent bobsCopyOfLanguages to Bob. Now lemme get on with my own life. I'll start my life by logging my preference for C# and admire the truthiness in my deep love for C#...

console.log(languages.compiled[1].preferred);
Enter fullscreen mode Exit fullscreen mode

...and lo and behold, my log shows:

false
Enter fullscreen mode Exit fullscreen mode

What, when did#$%!^#&**#...

Well, curse not.

This behaviour of Spread Syntax may be obvious to many, but for me, I had to sleep over it to think this through with fresh mind this morning.

The key here is to not forget that:

Objects are passed by reference in JavaScript

So, as long as you have that cleared, then you know that what you "spread" or "copied" to Bob is effectively a copy of your languages object. However, the nested object is still copied by reference.

So, yeah, it is what it is.

One way I deal with this kind of Truly Copying™️ a light-weight object like this is:

const bobsCopyOfLanguages = JSON.parse(JSON.stringify(languages));

Enter fullscreen mode Exit fullscreen mode

I hope you like my style of tech writing and learned something today!

P.S.: confession: C# is not my preferred language.

P.S.: If you do Vue, yo might be interested in my article about the Practical Use-cases of Mixins in Vue 2

Top comments (0)