What is the most efficient way to create an arbitrary length zero filled array in JavaScript?
相关问题
- Is there a limit to how many levels you can nest i
- How to toggle on Order in ReactJS
- void before promise syntax
- Keeping track of variable instances
- Can php detect if javascript is on or not?
I've tested all combinations of pre-allocating/not pre-allocating, counting up/down, and for/while loops in IE 6/7/8, Firefox 3.5, Chrome, and Opera.
The functions below was consistently the fastest or extremely close in Firefox, Chrome, and IE8, and not much slower than the fastest in Opera and IE 6. It's also the simplest and clearest in my opinion. I've found several browsers where the while loop version is slightly faster, so I'm including it too for reference.
or
If you use ES6, you can use Array.from() like this:
Has the same result as
Because
I was testing out the great answer by T.J. Crowder, and came up with a recursive merge based on the concat solution that outperforms any in his tests in Chrome (i didn't test other browsers).
call the method with
makeRec(29)
.Note added August 2013, updated February 2015: The answer below from 2009 relates to JavaScript's generic
Array
type. It doesn't relate to the newer typed arrays defined in ES2015 [and available now in many browsers], likeInt32Array
and such. Also note that ES2015 adds afill
method to both Arrays and typed arrays, which is likely to be the most efficient way to fill them...Also, it can make a big difference to some implementations how you create the array. Chrome's V8 engine, in particular, tries to use a highly-efficient, contiguous-memory array if it thinks it can, shifting to the object-based array only when necessary.
With most languages, it would be pre-allocate, then zero-fill, like this:
But, JavaScript arrays aren't really arrays, they're key/value maps just like all other JavaScript objects, so there's no "pre-allocate" to do (setting the length doesn't allocate that many slots to fill), nor is there any reason to believe that the benefit of counting down to zero (which is just to make the comparison in the loop fast) isn't outweighed by adding the keys in reverse order when the implementation may well have optimized their handling of the keys related to arrays on the theory you'll generally do them in order.
In fact, Matthew Crumley pointed out that counting down is markedly slower on Firefox than counting up, a result I can confirm — it's the array part of it (looping down to zero is still faster than looping up to a limit in a var). Apparently adding the elements to the array in reverse order is a slow op on Firefox. In fact, the results vary quite a bit by JavaScript implementation (which isn't all that surprising). Here's a quick and dirty test page (below) for browser implementations (very dirty, doesn't yield during tests, so provides minimal feedback and will run afoul of script time limits). I recommend refreshing between tests; FF (at least) slows down on repeated tests if you don't.
The fairly complicated version that uses Array#concat is faster than a straight init on FF as of somewhere between 1,000 and 2,000 element arrays. On Chrome's V8 engine, though, straight init wins out every time...
Here's the test page (live copy):
As of ECMAScript2016, there is one clear choice for large arrays.
Since this answer still shows up near the top on google searches, here's an answer for 2017.
Here's a current jsbench with a few dozen popular methods, including many proposed up to now on this question. If you find a better method please add, fork and share.
I want to note that there is no true most efficient way to create an arbitrary length zero filled array. You can optimize for speed, or for clarity and maintainability - either can be considered the more efficient choice depending on the needs of the project.
When optimizing for speed, you want to: create the array using literal syntax; set the length, initialize iterating variable, and iterate through the array using a while loop. Here's an example.
Another possible implementation would be:
But I strongly discourage using this second implantation in practice as it's less clear and doesn't allow you to maintain block scoping on your array variable.
These are significantly faster than filling with a for loop, and about 90% faster than the standard method of
But this fill method is still the most efficient choice for smaller arrays due to it's clarity, conciseness and maintainability. The performance difference likely won't kill you unless you're making a lot of arrays with lengths on the order of thousands or more.
A few other important notes. Most style guides recommend you no longer use
var
without a very special reason when using ES6 or later. Useconst
for variables that won't be redefined andlet
for variables that will. The MDN and Airbnb's Style Guide are great places to go for more information on best practices. The questions wasn't about syntax, but it's important that people new to JS know about these new standards when searching through these reams of old and new answers.I knew I had this proto'd somewhere :)
Edit: tests
In response to Joshua and others methods I ran my own benchmarking, and I'm seeing completely different results to those reported.
Here's what I tested:
Results:
So by my reckoning push is indeed slower generally but performs better with longer arrays in FF but worse in IE which just sucks in general (quel surprise).