how to decide when to use array or objects in javascript - javascript

I had an interview where the person asked me this question. Can anyone explains all the aspects so that i have a clear idea which structure to use when.

Arrays:
Arrays provide order, Object's don't (at least not yet).
Arrays can be optimized (speed and even the memory footprint), when used as non sparse lists with items of the same type.
Arrays provide a bunch of functions to work with this data-structure
Objects:
Objects are more generic
Using the Object as a Dictionary: lookups are faster than iterating over an Array to find the right item. return itemsById[id]
Code for Objects with the same hidden class can also be optimized.
Conclusion:
Arrays: use them if you think of the data as a list; same type improves performance but ain't a requirement.
To be more precise: lists have no gaps (missing indices), the data may have gaps, but the list shouldn't. If the list would have gaps, then the index has a meaning beyond just order, and it's probably a Dictionary with numeric keys.
Dictionaries: Plain Object used as a dictionary for the advantage of the fast lookup. Mentioned separate, because it's a different state of mind, having/dealing with a dictionary of items and dealing with an Object composing some properties.
Objects: A composition of properties of "some object". Like the body parts of a person. Or the "row" in a table of data: {id, firstName, lastName, ...}
Avoid enumerated properties. If you have sth. like {foo1, foo2, foo3, ...} foo is most likely a list of whatever, and should be built as such (just makes your life easier). unless this object is a dictionary

Related

Why use an array-like object in Javascript?

I get that since javascript allows numeric keys for objects, the existence of array-like objects is therefore technically possible, but why did they ever become common?
Maybe the thought was that these array-like objects don't just have numeric keys, e.g. arguments has the callee property, so they can't be proper arrays to accommodate those properties.
But in javascript, it's perfectly valid to treat an array as an object and use non-numeric keys:
var myArguments = [];
myArguments[0] = 0;
myArguments['callee'] = function(){console.log('callee')};
If the object is array-like and would benefit from having access to the functions it would otherwise inherit from the array prototype, what would be advantage of making it an array-like object instead?
Edit: in case it wasn't clear in my question, an array like object would be something like the arguments object that has sequential numeric properties starting from zero, and has a length property that is one less than the highest numeric key. It also doesn't inherit from the array prototype, and doesn't provide access to array methods.
There is no big advantage, as you can access objects and arrays in very similar ways, array[number] for arrays, and object.propery, and object["property"] for objects. Arrays are better for storing data, not functions, in my opinion, and objects are better for storing sets of functions, in my opinion. For example, arrays could store your answers in a memory game, but an object would store the command for the game, like start or end.
I think the biggest advantage of using Array-Like object, is an object itself. An object has less overhead than an Array.
Can read: Array vs. Object efficiency in JavaScript
The other advantage of using objects, Language does not have to create/allocate contiguous memory as in Array. The object is more dynamic in nature. The array has to create a memory block in advance. and update on overload.
Read more: How are the JavaScript Arrays internally resizing?
Another factor, I think lookup in a map or object is faster.
Edit: As #Bergi stated, I forgot to add length property to the object. Also, I realized that my answer was not relevant. So I updated it after a short research.
In Typescript an arraylike object is defined like below:
interface ArrayLike<T> {
length: number;
[n: number]: T;
}
There are two main examples of array-like objects: arguments and HTMLCollection. The reason for using an array-like object is to use an array as only a data container without any behavior. As you could realize, if you try to use, say forEach, on arguments object you will get a type error since it's not defined on it. If you strictly believe that the array you are creating is only to be used as a data container without any methods whatsoever, then go with array-like objects. However, important to notice that they are getting scarcer day by day especially after ES6.
Actually Array in JS is an Object :)
As long as You need array, it is bad idea to create array-like objects, because JS engines optimize speed of arrays.
Yet, its possible.

Dynamic property as key VS List of objects in Javascript - which one will be more efficient

I need a data structure something like HashMap(in JAVA) where I want map status of user using user id as a key . So I can easily create a map dynamically like this:-
var mapOfIdVsStatus = {
123: "true",
456: 'false'
}
alert(JSON.stringify(mapOfIdVsStatus));
In my scenario, new user id and status will be added/updated very frequently that is
Object.keys(mapOfIdVsStatus).length;
will increase. But this will help to search status of a user in a faster way.
I can do this in an alternative way like this:
var user1={
id:123,
status: true
}
var user2={
id:456,
status: false
}
var listOfUser = [];
listOfUser.push(user1);
listOfUser.push(user2);
alert(JSON.stringify(listOfUser));
I can also search status in the list for a user but need extra effort like looping..etc
Considering a lots of Add, Search and Memory Optimization which one will be my best choice?
Behaviors would be like:
Are keys usually unknown until run time? -YES
Do you need to look them up dynamically? - YES
Do all values have the same type? -YES
Can they be used interchangeably?- NO
Do you need keys that aren't strings? - Always String
Are key-value pairs often added or removed?- Always added, No removal
Do you have an arbitrary (easily changing) amount of key-value pairs?- YES
Is the collection iterated? - I want to avoid iteration for faster
access.
The best choice is an ES6 Map. MDN gives some hints when to use it instead of a plain object:
If you're still not sure which one to use, ask yourself the following questions:
Are keys usually unknown until run time? Do you need to look them up dynamically?
Do all values have the same type? Can they be used interchangeably?
Do you need keys that aren't strings?
Are key-value pairs often added or removed?
Do you have an arbitrary (easily changing) amount of key-value pairs?
Is the collection iterated?
If you answered 'yes' to any of those questions, that is a sign that you might want to use a Map.
The object, hands-down. Property lookup will be, at worst, a kind of hashmap-style lookup rather than a linear search.
If you do this, it's best to create the object without a prototype:
var mapOfIdVsStatus = Object.create(null);
...so it doesn't inherit properties from Object.prototype.
On ES2015-compliant JavaScript engines, you might also look at Map. Map is specifically designed to be a simple key/value map, and so is unencumbered by any object-ness. On Chrome and Firefox, at least in my simple test, it performs as well or better than object lookup with string keys (this is Chrome; Firefox seems to be similar):
...but object lookup easily outpaces Map with number keys (this is also Chrome, on Firefox it was only twice as fast, not just under three times as fast):
But, those tests only test querying values once they've been added, not the tumult of adding new ones. (The updates you're talking about wouldn't matter, as you're changing the properties on the stored objects, not the thing actually stored, if I'm reading right.)
One really key thing is that if you need to remove entries, with an object you're better off setting the property's value to null or undefined rather than using delete. Using delete on an object can really, really slow down subsequent operations on it.

If a JSON array is an object, why is it listed among the primitives?

When I first read the JSON format specification, I was under the impression that an object was a collection of key-value pairs (with the value being of any type) and an array was a collection of zero or more elements of the same type.
object (mixed values):
{
"key": "value",
"key2": 2
}
array (single type):
[1, 2, 3]
["one", "two", "three"]
[
{"key": "value"},
{"key2": 2}
]
I encountered some examples that included arrays with elements of mixed types. After testing that this is legitimate in Node.js, I'm left wondering: why have two different collection types that are so similar?
array (mixed types):
[1, "two", {"three": 4}]
The only major difference I can see is that arrays don't require a "key" for every "value". Are there any other significant differences?
EDIT:
Given the duplicate question of the original, and that an array is a dressed up object, I've modified the question slightly. (Apologies to the original answers.)
My best guess is that arrays are extremely common and adding a syntax and predefined class for them is mostly for convenience.
Possible duplicate/reference question: What is the difference between an array and an object?
A "collection" can have many different attributes (in the meaning of "how it behaves"):
does it have a guaranteed order?
is it a key-value store where keys can be arbitrary?
is it homogeneous or can it be heterogenous?
does it grow as you put in items or does it have a fixed size?
etc. etc.
Any combination of these attributes gives you a different type of collection. These are variously known in different languages as lists, tuples, arrays, dictionaries, hashes, objects etc.. Each has a different tradeoff in terms of behaviour vs. strictness vs. complexity vs. resource usage etc.. Javascript chose to implement two types:
lists, called "arrays" in Javascript:
has a guaranteed order
keys are numeric only
numeric keys are continuous (they're actually not, arrays are sparse, but when iterating over the collection it should be considered continuous)
can be heterogenous
dictionaries, called "objects" in Javascript:
no guaranteed order
key-value associative collection
can be heterogenous
You choose between the two based on which attribute is important to you. The choice typically comes down to ordered vs. unordered and key-value association vs. no relevancy for keys. Note that Javascript's particular implementation of both is essentially all hash maps, because everything in Javascript is an object is a function is an object; but their usage differs nonetheless by the above points.
[] instanceof Object
> true
Arrays are objects with convenience methods [see this answer].
Besides their nature, of course you want an ordered structure you can iterate over [the array], and a key:value collection whose values you want to access via either dot or bracket notation [someObj.someKey or someObj[someKey]].

Are there any pitfalls to storing collections of objects with unique ids as an associative array with ids as keys, rather than as a regular array?

I've been following Backbone Collection's convention of having arrays of data objects and using _.find/findWhere etc to loop through the array, even when I wasn't using Backbone. However it seems like it would be more efficient to instead store them as an associative array with the id as keys if I know that they will be unique. Are there any pitfalls to this that I'm not seeing?
So basically:
var map = {};
map["someId"] = someObject;
map["someOtherId"] = someOtherObject;
// ...later to get the object:
var o = map["someId"];
If so, then the answer to "are there any pitfalls...I'm not seeing" is "no": Looking up properties on objects is a very common operation, which JavaScript engines do very quickly.
In fact, since normal JavaScript arrays aren't really arrays at all, it's markedly more efficient to look things up this way rather than storing them in arrays and using forEach or similar to find them. Every time you get an entry from an array (e.g., a[0] or whatever), that's a property access operation, just like looking up a property in an object. (In fact, that's exactly what it is, barring the JavaScript engine knowing it can optimize the operation.) Getting an element from one of the new typed arrays is faster because they really are arrays (although searching through them will still be non-trivial), but getting an element from a standard array is a property lookup on an object, so you might as well just do one lookup (on your map, using your key) instead.
(Side note: In JavaScript, the term "associative array" isn't usually used. It's just an object. Sometimes you also hear "map".)

Storing components in an Entity System

Note: this introduction is about entity systems. But, even if you don't know what these are, or haven't implemented them yourself, it's pretty basic and if you have general Javascript experience you will probably qualify more than enough to answer.
I am reading articles about Entity Systems on the T=machine blog.
The author, Adam, suggests that an entity should just be an id, that can be used to obtain it's components (ie, the actual data that the entity is supposed to represent).
I chose the model where all entities should be stored in "one place", and my primary suspects for implementing this storage are the array-of-arrays approach many people use, which would imply dynamic entity id's that represent the index of a component belonging to an entity, while components are grouped by type in that "one place" (from now on I'll just call it "storage"), which I plan to implement as a Scene. The Scene would be an object that handles entity composition, storage, and can do some basic operations on entities (.addComponent(entityID, component) and such).
I am not concerned about the Scene object, I'm pretty sure that it's a good design, but what I am not sure is the implementation of the storage.
I have two options:
A) Go with the array-of-array approach, in which the storage looks like this:
//storage[i][j] - i denotes component type, while j denotes the entity, this returns a component instance
//j this is the entity id
[
[ComponentPosition, ComponentPosition, ComponentPosition],
[ComponentVelocity, undefined, ComponentVelocity],
[ComponentCamera, undefined, undefined]
]
//It's obvious that the entity `1` doesn't have the velocity and camera components, for example.
B) Implement the storage object as a dictionary (technically an object in Javascript)
{
"componentType":
{
"entityId": ComponentInstance
}
}
The dictionary approach would imply that entity id's are static, which seems like a very good thing for implementing game loops and other functionality outside the Entity System itself. Also, this means that systems could easily store an array of entity ids that they are interested in. The entityId variable would also be a string, as opposed to an integer index, obviously.
The reason why I am against array-of-arrays approach is that deleting entities would make other entity ids change when a single entity is deleted.
Actual implementation details may wary, but I would like to know which approach would be better performance wise?
Things that I am also interested in (please be as cross-platform as possible, but if needed be, use V8 as an example):
How big is the overhead when accessing properties, and how is that implemented under the hoof? Lets say that they are being access from inside the local scope.
What is undefined in memory, and how much does it take? I ask this, because in the array-of-arrays approach all of the inner arrays must be of the same length, and if an entity doesn't have a certain component, that field is set to undefined.
Don't worry about the Array. It is an Object in JavaScript i.e. no "real" arrays, it's just the indices are a numeric "names" for the properties of the object (dictionary, hash, map).
The idea is simple, an Array has a length property that allows for loops to know where to stop iterating. By simply removing an element off the Array (remember, it's an Object) the length property doesn't actually change. So...
// create an array object
var array = ['one','two', 'three'];
console.log(array.length); // 3
// these don't actually change the length
delete array['two']; // 'remove' the property with key 'two'
console.log(array.length); // 3
array['two'] = undefined; // put undefined as the value to the property with key 'two'
console.log(array.length); // 3
array.splice(1,1); // remove the second element, and reorder
console.log(array.length); // 2
console.log(array); // ['one','three']
You've got to realize that JavaScript doesn't "work" like you expect. Performance wise objects and arrays are same i.e. arrays are accessed like dictionaries;
Scope is not like other "c style" languages. There are only global and function scopes i.e. no block scope (never write for(var i) inside another for(var i));
undefined in memory takes exactly the same amount as null . The difference is that null is deliberate missing of value, while undefined is just accidental (non-deliberate) missing;
Don't check if a field exists by doing if(array['two']) because, a field can actually hold the falsy values of undefined, null, 0, "", false and evaluate as false. Always check with if('two' in array);
When looping with for(key in array) always use if(array.hasOwnProperty(key)) so you don't iterate over a prototype's property (the parent's in a manner of speaking). Also, objects created by a constructor function might loop with the 'constructor' key also.

Categories