Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does javascript array with very high index numbers lead to crash / slow down / trouble?

Basically the code that broke my node js express server was this:

resultArr = [];
resultArr["test"] = [];
resultArr["test"][2015073012] = someObject;

when I changed this to this, it ran without problems

resultArr = [];
resultArr["test"] = {};
resultArr["test"][2015073012] = someObject;

I did work like this in a loop.

Why did it break my app?

like image 606
Toskan Avatar asked Jul 31 '15 05:07

Toskan


1 Answers

As you found, you shouldn't be using arrays for this, you should be using objects. But you should go a step further and use an object for the top level as well. And since your 2015073012 value will be used as a string, it's a good practice to make it one from the start:

var results = {};
results.test = {};
results.test['2015073012'] = someObject;

or:

var results = {};
results['test'] = {};
results['test']['2015073012'] = someObject;

Now you won't have any problem in any JavaScript engine.

(As an aside, I changed the name from resultArr to results so the name doesn't make it sound like it's an array.)

JavaScript arrays are for cases where you have sequential entries like array[0], array[1], array[2], etc. When you have arbitrary strings or arbitrarily large numbers for keys, do not use an array, use an object.

Don't be confused by other languages such as PHP that have a single array type which serves both as a sequential 0,1,2,3,... array and as a dictionary of key-value pairs. JavaScript has both arrays and objects: use arrays for the sequential case and objects for the key-value case.

Back to your question, why did this code break:

resultArr = [];
resultArr["test"] = [];
resultArr["test"][2015073012] = someObject;

One possible explanation is that the JavaScript engine is doing exactly what you told it to do when you assign a value to the [2015073012] array index: it creates an array with 2,015,073,013 entries (one more than the value you gave, because array indexes start at 0). That is over two billion entries in your array! You can probably see how that would cause a problem - and it certainly isn't what you intended.

Other engines may realize that this is a ridiculously large number and treat it as a string instead of a number, as if you'd used an object instead of an array in the first place. (A JavaScript array is also an object and can have key-value pairs as well as numeric indices.)

In fact, I crossed my fingers and tried this in the JavaScript console in the latest version of Chrome, and it worked with no problem:

a = [];
a[2015073012] = {};

But you weren't as lucky. In any case, you should always use objects instead of arrays for this kind of use, to insure that they are treated as key-value pairs instead of creating enormous arrays with mostly-empty elements.

like image 186
Michael Geary Avatar answered Oct 11 '22 00:10

Michael Geary