Is the spread operator slower than a for loop in JavaScript?
JavaScript offers several ways to find the smallest and largest numbers in a list, including the built-in Math functions and sorting the array numerically. I compare the performance of 5 methods using jsPerf ? and the spread operator loses.
Photo by Leio McLaren (@leiomclaren) on Unsplash
Sometimes, given an array of numbers in JavaScript, the smallest or largest value needs to be identified ? and quickly!
There are several built-in ways to find a minimum or maximum value from an array in JavaScript, including using the Math functions with the spread operator (?) and sorting the array numerically with .sort().
In this article, I explain how each method works, then I compare the performance of 5 different methods of finding the minimum and maximum values of an array of numbers in JavaScript.
Photo by Gautier Salles on Unsplash
Using Math functions
The built-in Math functions Math.min() and Math.max() do exactly what one would expect ? they return the smallest or largest number of the list of numbers passed to them as arguments.
Since Math.min() and Math.max() both expect the numbers as arguments, and not an array, they do not seem at first choice to be good options for getting the smallest or largest number from an array:
On first glance, it looks like we need a different approach. Thankfully, using the ES6 feature spread syntax (?) makes arrays easily compatible with these functions, as I explain in the next section.
Photo by Quino Al on Unsplash
Math.min(?array) and Math.max(?array)
?[The spread] operator causes the values in the array to be expanded, or ?spread,? into the function?s arguments.? ? Joel Lovera on jstips.co
The spread operator (?) in JavaScript can expand an array of numbers into the list of arguments, such as with Math.min() & Math.max():
Using the three magic dots (?) makes it easy to call any function expecting arguments, like these built-in Math functions, using an array.
Photo by Joe Cook on Unsplash
Without the spread operator
If one is programming to support older browsers, like Internet Explorer, and not using a tool like Babel for compiling the JavaScript code into older syntax with a plugin like babel-plugin-transform-spread, then the spread operator is not going to work.
Here is the current browser compatibility chart for the spread operator:
Calling the function Function.prototype.apply() will have the same effect as the spread syntax:
Note that the first argument to .apply() is the target for this, which in this case does not matter, so I passed in null as the first argument.
Photo by Mathias Elle on Unsplash
Sorting the list numerically
JavaScript defaults to a lexicographical (alphabetical) sort, where numbers are coerced into strings and then sorted alphabetically.
Sorting an array of numbers numerically in JavaScript is accomplished by passing the Array.prototype.sort() function a ?comparison operator.?
For example, the code .sort((a,b) => a-b) will sort numbers in ascending order from smallest to largest.
Once sorted, the first number will be the min and the last the max:
Photo by Phil Reid on Unsplash
Using a for loop or .reduce()
Either a for loop or the Array.prototype.reduce() method can be used to find the minimum and maximum numbers in an array:
Brandon Morelli reported previously on Codeburst.io that these methods may be fastest, so I compare the performance of all 5 methods next.
Photo by Stphane Juban on Unsplash
Performance testing
I ran some tests using jsPerf, a free tool for testing the performance of JavaScript code in the browser. Each code sample finds the minimum and maximum of a random array of 40 numbers. Here are the results:
Wow! For some reason the spread operator is half the speed of the other methods. Since using .apply() works quickly, it appears using the spread operator over 40 arguments really slows things down.
It appears to not be the fault of the Math.min() or Math.max() functions themselves per se, since a for loop that avoids those functions has basically the same performance for this test case of 40 random items.
Photo by Quentin Rey on Unsplash
A second look: 4000 items
I updated the test suite to generate a 4000 item array to examine if it changes the comparative performance of finding the min and max.
Indeed, it does, with the spread operator being 92% slower:
This shows that the performance drop is associated with the spread operator in a way that scales with the number of arguments being spread.
With very large arrays, the for loop is fastest by far, with .apply() coming in second, .sort() and .reduce() tied for third, and spread dead last.
It is worth noting that using Babel to compile the code may restore some performance for large and very large arrays, since it will transpile the spread operator to the .apply() syntax using babel-plugin-transform-spread.
Photo by Andy Brunner on Unsplash
A third look: Just 3 items
However, don?t throw the spread operator out just quite yet ? there is no performance difference when we drop down to 3 items:
So, for day-to-day use, the spread operator works brilliantly.
Meanwhile, the iterative for loop is 3% slower than the spread operator when only dealing with an array of only 3 items.
Photo by Joshua Earle on Unsplash
Conclusion
There are several ways to find the smallest and largest numbers in a JavaScript array, and the performance of each method varies based on the number of values in the array.
The most convenient way is using the syntax Math.min(…array) and Math.max(…array)? using ES6?s spread operator (?) to spread the array into the arguments expected by JavaScript?s built-in Math functions.
However, when dealing with large arrays of 40 items or more, using the spread operator has significantly worse performance compared to other methods of finding the minimum and maximum.
What to do for larger arrays
For large arrays, using Math.min.apply(null,array) and Math.max.apply(null,array) restores the lost performance from the spread operator and allows one to continue to use the built-in Math functions.
This is actually exactly what Babel does with babel-plugin-transform-spread, so compiling your JavaScript code will help with arrays around 40 items.
Finally, with very large arrays of 4000 items or more, a for loop is the fastest method by far, so keep that in mind. It may be ugly, but it works.
Now go find some minimums and maximums! ?
Photo by Hannah Reding on Unsplash
Further reading
- GeeksforGeeks explores using .map() and .reduce() to find min/max:
Max/Min value of an attribute in an array of objects in JavaScript – GeeksforGeeks
Given an array of objects and the task is to get the maximum and minimum value from the array of objects. There are a?
www.geeksforgeeks.org
- Dan Vega finds the maximum id in an array of objects on his blog:
How to find the max id in an array of objects in JavaScript
I was recently putting together a tutorial for some students and I came across an issue that I am sure we have all come?
www.danvega.dev
- The site w3resource has a visual tutorial on finding a minimum:
JavaScript Math: Find the lowest value in an array – w3resource
Write a JavaScript function to find the lowest value in an array. Test Data : console.log(min([12,34,56,1]))?
www.w3resource.com
- The library d3-array includes the useful .minIndex() & .maxIndex(), although a for loop will likely be faster for very large arrays:
d3/d3-array
Array manipulation, ordering, searching, summarizing, etc. – d3/d3-array
github.com
- Brandon Morelli found for loops are fast in his article on codeburst.io:
JavaScript: Finding Minimum and Maximum values in an Array of Objects
Three potential solutions. But which is fastest?
codeburst.io
- Previous research on very large arrays of 250,000 items published on the Microsoft devblog showed that for loops are the fastest method by far:
Find the index of the smallest element in a JavaScript array | The Old New Thing
Today’s Little Program isn’t even a program. It’s just a function. The problem statement is as follows: Given a?
devblogs.microsoft.com
Photo by Rachel Cook on Unsplash