Array vs. Object efficiency in JavaScript
The short version: Arrays are mostly faster than objects. But there is no 100% correct solution.
Update 2017 - Test and Results
var a1 = [{id: 29938, name: 'name1'}, {id: 32994, name: 'name1'}];
var a2 = [];
a2[29938] = {id: 29938, name: 'name1'};
a2[32994] = {id: 32994, name: 'name1'};
var o = {};
o['29938'] = {id: 29938, name: 'name1'};
o['32994'] = {id: 32994, name: 'name1'};
for (var f = 0; f < 2000; f++) {
var newNo = Math.floor(Math.random()*60000+10000);
if (!o[newNo.toString()]) o[newNo.toString()] = {id: newNo, name: 'test'};
if (!a2[newNo]) a2[newNo] = {id: newNo, name: 'test' };
a1.push({id: newNo, name: 'test'});
}
Original Post - Explanation
There are some misconceptions in your question.
There are no associative arrays in Javascript. Only Arrays and Objects.
These are arrays:
var a1 = [1, 2, 3];
var a2 = ["a", "b", "c"];
var a3 = [];
a3[0] = "a";
a3[1] = "b";
a3[2] = "c";
This is an array, too:
var a3 = [];
a3[29938] = "a";
a3[32994] = "b";
It's basically an array with holes in it, because every array does have continous indexing. It's slower than arrays without holes. But iterating manually through the array is even slower (mostly).
This is an object:
var a3 = {};
a3[29938] = "a";
a3[32994] = "b";
Here is a performance test of three possibilities:
Lookup Array vs Holey Array vs Object Performance Test
An excellent read about these topics at Smashing Magazine: Writing fast memory efficient JavaScript
JavaScript object vs. array lookup performance
The answer to this is browser dependent, however, there are a few performance tests on jsperf.com on this matter. It also comes down to the size of your data. Generally it is faster to use object key value pairs when you have large amounts of data. For small datasets, arrays can be faster.
Array search will have different performance dependent on where in the array your target item exist. Object search will have a more consistent search performance as keys doesn't have a specific order.
Also looping through arrays are faster than looping through keys, so if you plan on doing operations on all items, it can be wise to put them in an array. In some of my project I do both, since I need to do bulk operations and fast lookup from identifiers.
A test:
http://jsben.ch/#/Y9jDP
Javascript Set vs. Array performance
Ok, I have tested adding, iterating and removing elements from both an array and a set. I ran a "small" test, using 10 000 elements and a "big" test, using 100 000 elements. Here are the results.
Adding elements to a collection
It would seem that the .push
array method is about 4 times faster than the .add
set method, no matter the number of elements being added.
Iterating over and modifying elements in a collection
For this part of the test I used a for
loop to iterate over the array and a for of
loop to iterate over the set. Again, iterating over the array was faster. This time it would seem that it is exponentially so as it took twice as long during the "small" tests and almost four times longer during the "big" tests.
Removing elements from a collection
Now this is where it gets interesting. I used a combination of a for
loop and .splice
to remove some elements from the array and I used for of
and .delete
to remove some elements from the set. For the "small" tests, it was about three times faster to remove items from the set (2.6 ms vs 7.1 ms) but things changed drastically for the "big" test where it took 1955.1 ms to remove items from the array while it only took 83.6 ms to remove them from the set, 23 times faster.
Conclusions
At 10k elements, both tests ran comparable times (array: 16.6 ms, set: 20.7 ms) but when dealing with 100k elements, the set was the clear winner (array: 1974.8 ms, set: 83.6 ms) but only because of the removing operation. Otherwise the array was faster. I couldn't say exactly why that is.
I played around with some hybrid scenarios where an array was created and populated and then converted into a set where some elements would be removed, the set would then be reconverted into an array. Although doing this will give much better performance than removing elements in the array, the additional processing time needed to transfer to and from a set outweighs the gains of populating an array instead of a set. In the end, it is faster to only deal with a set. Still, it is an interesting idea, that if one chooses to use an array as a data collection for some big data that doesn't have duplicates, it could be advantageous performance wise, if there is ever a need to remove many elements in one operation, to convert the array to a set, perform the removal operation, and convert the set back to an array.
Array code:
var timer = function(name) { var start = new Date(); return { stop: function() { var end = new Date(); var time = end.getTime() - start.getTime(); console.log('Timer:', name, 'finished in', time, 'ms'); } }};
var getRandom = function(min, max) { return Math.random() * (max - min) + min;};
var lastNames = ['SMITH', 'JOHNSON', 'WILLIAMS', 'JONES', 'BROWN', 'DAVIS', 'MILLER', 'WILSON', 'MOORE', 'TAYLOR', 'ANDERSON', 'THOMAS'];
var genLastName = function() { var index = Math.round(getRandom(0, lastNames.length - 1)); return lastNames[index];};
var sex = ["Male", "Female"];
var genSex = function() { var index = Math.round(getRandom(0, sex.length - 1)); return sex[index];};
var Person = function() { this.name = genLastName(); this.age = Math.round(getRandom(0, 100)) this.sex = "Male"};
var genPersons = function() { for (var i = 0; i < 100000; i++) personArray.push(new Person());};
var changeSex = function() { for (var i = 0; i < personArray.length; i++) { personArray[i].sex = genSex(); }};
var deleteMale = function() { for (var i = 0; i < personArray.length; i++) { if (personArray[i].sex === "Male") { personArray.splice(i, 1) i-- } }};
var t = timer("Array");
var personArray = [];
genPersons();
changeSex();
deleteMale();
t.stop();
console.log("Done! There are " + personArray.length + " persons.")
Javascript efficiency: big object vs many arrays
Which way is better? Well, we are talking about basic OOP, here: you have many different "arrays" which contains information about a client, and the information of a client is scattered through many different arrays, and every array must share the index with another 10 arrays.
You have a problem: what happens when you remove a socket from the sockets array, but do not remove the position? BUG!
So, if a client is a client, treat it as a whole, with 10 (in your example) composite properties, about the client's socket, his attributes, etc.
Please, don't think about "efficiency". Your question's answer is not about efficiency, is about maintainability, robustness and simplicity. This things usually drive you naturally toward better performance, but you should care about performance only if you have a performance problem.
Remember (write it down on a wall): Premature optimization is the root of all evil.
Performance of array includes vs mapping to an Object and accessing it in JavaScript
It's true that object lookup occurs in constant time - O(1) - so using object properties instead of an array is one option, but if you're just trying to check whether a value is included in a collection, it would be more appropriate to use a Set
, which is a (generally unordered) collection of values, which can also be looked up in linear time. (Using a plain object instead would require you to have values in addition to your keys, which you don't care about - so, use a Set
instead.)
const set = new Set(['foo', 'bar']);
console.log(set.has('foo'));
console.log(set.has('baz'));
Related Topics
Split Large String in N-Size Chunks in JavaScript
JavaScript Function Declaration and Evaluation Order
How to Turn JavaScript Array into Comma-Separated List
Why Do Results Vary Based on Curly Brace Placement
Image Loaded Event in for Ng-Src in Angularjs
How to Access Shadow Dom Elements Through the Parent Document
Check Ctrl/Shift/Alt Keys on 'Click' Event
JavaScript Filereader - Parsing Long File in Chunks
How to Pass Variable Value Between Different HTML Pages in JavaScript
Accessing Private Member Variables from Prototype-Defined Functions
JavaScript Swap Array Elements
What Does the Plus Sign Do in '+New Date'
How to Load Data from a CSV File in D3 V5
How to Update an "Array of Objects" with Firestore
How to Get Jquery.Trigger('Click'); to Initiate a Mouse Click