A quick prelude: I wrote the first draft of this post a couple of months ago, but it still needed editing and polishing. Then Rich Snapp published The reduce ({…spread}) anti-pattern and made all the main points I was going to make.
Damn, I’ve done that thing again where I do 80%-90% of something, procrastinate about finishing it, then someone else releases a finished version that gets widely shared. I *really* need to get better at completing things.
— Gilmore (@iamnotyourbroom) 16 June 2019
Feeling rather deflated, I initially abandoned the draft. However, to force myself to complete things, I’m publishing it anyway. Although our primary argument is the same, we approach the topic from slightly different angles. I recommend reading Rich’s post too as it’s well-written, and he explains some things better than I do. But mine has a bonus grumpy rant at the end. Contrast and compare.
Object spread — a primer
The object spread syntax has become one of the more readily-adopted[citation needed] pieces of the ever-evolving ECMAScript specification. Over the past few years I’ve worked on several application codebases that have made use of it, and seen many more open source libraries using it.
First I should define what I mean by the object spread syntax. It’s best to explicitly set the terms of reference here, because different people might have different interpretations of it. Other people might have used the syntax but not known what it was called.
Object spread, at its simplest, is used for copying the keys and values of one object into a new object. It’s important to note that it does a shallow copy rather than a deep copy, but in many cases that’s all that’s required anyway. (For more details on shallow vs deep copies, see this Stack Overflow post.)
let sourceObject = { element: 'input', type: 'radio' };
let sourceCloned = { ...sourceObject };
// A new copy of the original: { element: 'input', type: 'radio' }
let extendedObject = { ...sourceObject, name: 'newthing', type: 'checkbox' };
// A modified copy: { element: 'input', name: 'newthing', type: 'checkbox' }
The problem
Object spread syntax is not a problem in and of itself. Quickly and easily copying an object’s data to another object is a very common use case. Indeed, the plethora of solutions that were created in the years beforehand show how much it was needed. Long gone are the days where some projects would include the entirety of jQuery just so they could use $.extend()
.
The problem arises when it becomes the only way to assign properties to an object in a codebase. Over the past few years I’ve noticed a trend of using object spread wherever possible, even if it isn’t the best tool for the job.
In the worst cases, it has caused exponential performance bottlenecks. Helping someone fix a slow-running script is what prompted me to write this post. Object spread syntax should be used with caution.
Continue reading