JavaScript "Associative" Object vs. Array - javascript

at the moment I am using an object to simulate an associatve array.
The object acts like a one to many relationship table from mysql
For Example:
var obj = {
105: [],
200: []
//...
}
My property names are only numeric so I found out that I could use an array, too.
But then the empty entries between the indices are filled with undefined.
var arr = [];
arr[10] = "Value";
arr[15] = "Value 2";
//arr => [undefined*10, "Value", undefined*4, "Value 2"]
So when I am going to iterate over that array I have to check if the value at the current index is set.
So the question is, which of the solutions is faster or better.
Using an object or an array where
the empty space between the indizes is filled with undefined values.

If you need a key-value association, you need an object.
If you want an ordered list in which the keys don't really matter, an array it is.
FYI, the indices "between" set indices in an array are not actually "filled" with undefined; you merely get the undefined value when you try to access a non-existing property on any object:
({}).foo; // undefined

You are asking which is "faster or better". For "better" many possible answers exist, but "faster" has a clearer answer: as others pointed out there is hardly any speed difference between Object and Array. Both have the same roots in the prototype hierarchy. An Array's empty values are not "filled".
Regarding your use case the bottleneck will not be the object, but how you loop it! This actually does make a difference: for loops are faster than any other way of looping. But you have the problem of the non-continuos numeric indices.
Therefore: just benchmark how long it takes if you do
for(key in object)
keys = Object.keys() and for(var i = 0; i < keys.length; i++)
as these two should be your fastest options.

Related

Index of javascript object in array of objects

I have an array of objects in javascript, something like
var arrayobj = [{a:'a'},{b:'b'},{c:'c'}] (but with more complex values).
Now I check the index of some object manually, like arrayobj[1]
And I got Object {b: "b"}
Now I type arrayobj.indexOf({b:'b'});
and the response is -1 (aka not found).
Anyone could tell me why this happens? I have read the documentation on indexOf method and arrays, but I still have no clue.
Thanks in advance!
indexOf checks for equality (specifically strict equality, ===, but it doesn't matter for this question). Two different objects are not equal to each other even if they have the same properties. The object in your array and the one you pass to indexOf are different objects, and so they don't match.
If you searched for the same object, it would find it:
var b = {b:'b'};
var arrayobj = [{a:'a'},b,{c:'c'}];
console.log(arrayobj.indexOf(b)); // 1
The indexOf method returns the first index at which a given element can be found in the array, or -1 if it is not present.
arrayobj is an array of objects, In first case arrayobj[1] it will return the element at index 1.
In second case arrayobj.indexOf({b:'b'}) is not referring to the object which in the arrayobj but it is a different object.
arrayobj.indexOf({b:'b'})
You are supplying a new object in the indexOf method although contents are same. IndexOf will check for strict equality so references of the objects need to be the same
When you call arrayobj.indexOf({b:'b'}) the Object {b:'b'} is different from the object in your array. These 2 objects have the same "value" but are distinct in the memory.
For exemple if you do this :
var object = {b:'b'}
var arrayobj = [{a:'a'},object,{c:'c'}]
or
var arrayobj = [{a:'a'},{b:'b'},{c:'c'}]
var object = arrayobj[1]
arrayobj.indexOf(object) will return 1 because it's really the same object and not a "copy"
Javascript IndexOf function will work only for value types and not for reference types in your case. Like when you are passing {b:'b'} to indexOf function then it is all in all a complete different object / reference. If you first fetch object from list and then check that reference in list then it will definitely return greater then -1 if object / reference exist
var arrayobj = [{a:'a'},{b:'b'},{c:'c'}];
var obj = arrayobj[1];
console.log(arrayobj.indexOf(obj)); console.log(arrayobj.indexOf({b:'b'}));
you can use for loop instead of built-in function.

Is an array in JS actually filled with empty spaces or when printed is it filled with zeros?

I have an array:
mydata =[];
i am storing values in the array by using a numeric key that can be somewhat big
mydata[13525] = 1;
However if i only store one item as the above, when i print the array in the console it prints 13524 commas before the object, nevertheless the debugger tells me it has length 13526 and there is only one element in the array.
I am confused as i understood that JS arrays do not required every position to be filled and certainly this might consume a lot of memory on bigger numbers. Can you explain please?
The .length property of an array represents the highest index plus one in the array that has been assigned a value.
When you do not assign intermediate values (and thus have a sparse array), the intervening values that you have not assigned are undefined which is essentially the "nothing here" value in Javascript. The console chooses to display arrays by trying to show you every value between 0 and the end of the array which is simply not a very good way to display a sparse array that is mostly empty. That's more an artifact of a design choice in the console than anything else. One could design a different way to display contents of an array that would handle sparse arrays differently.
Arrays are most efficient if you use consecutive indexes started from 0. That's what they are mostly designed for and what many implementations are optimized for since a runtime can do some optimized things if it knows there is a sequential set of values.
If you know you're going to mostly not be using sequences of numeric indexes starting from 0 and as such the .length property is of little use to you, then perhaps a plain object with arbitrary properties is a better choice.
var mydata = {};
mydata[13525] = 1;
console.log(mydata[13525]); // 1
console.log(mydata.length); // undefined - no .length property on an object
console.log(myData); // {1: 13525}
If you only want to print any non-null value in the array, instead of printing the whole array I'd use a for loop that only prints non-null values. It'd be something like this...
for (i = 0; i < mydata.length; i++) {
if(mydata[i]!= null){
console.log(mydata[i]);
}
}
javascript array is bit different from others,
var foo = [1, 2, 3, 4, 5, 6];
foo.length = 3;
foo; // [1, 2, 3]
foo.length = 6;
foo.push(4);
foo; // [1, 2, 3, undefined, undefined, undefined, 4]
While the getter of the length property simply returns the number of elements that are contained in the array, in setter, a smaller value truncates the array, larger value creates a sparse array. Guess what the setter mydata[13525] = 1; would do.
src: Javascript Garden
Edit:
to print/use only the values present, you can do
mydata.forEach(function(v){console.log(v);});

Javascript: For in loops iterating over properties or indices?

Just started learning Javascript. Recently I used a for-in loops to iterate over properties of an object. For example...
var someObject = { a:1, b:2 };
for(var property in someObject){
console.log(property);
}
This would print...
"a"
"b"
However, when I use it to iterate over an array...
var someArray = ["a","b","c"];
for(var element in someObject){
console.log(element);
}
The indices, rather than the elements, get printed...
"0"
"1"
"2"
Why is this the case? In general, do JS for-in loops print properties only when iterated over objects and indices for everything else?
If it prints indices with the exception of objects, why would one ever use a classic for loop such as
for(var i=0,i<someNumber,i++)
when one can just use a for in loop? Especially since this seems a lot more concise?
for(var i in something)
Am I even supposed to use for-in loops for anything besides objects?
Thanks!
Quoting from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in#Description
for..in should not be used to iterate over an Array where index order
is important. Array indexes are just enumerable properties with
integer names and are otherwise identical to general Object
properties. There is no guarantee that for...in will return the
indexes in any particular order and it will return all enumerable
properties, including those with non–integer names and those that are
inherited.
Because the order of iteration is implementation dependent, iterating
over an array may not visit elements in a consistent order. Therefore
it is better to use a for loop with a numeric index (or Array.forEach
or the non-standard for...of loop) when iterating over arrays where
the order of access is important.
So, Don't rely on for..in for iterating over an Array.
And to answer
The indices, rather than the elements, get printed... Why is this the
case?
The answer has already been quoted above.
Array indexes are just enumerable properties with integer names and
are otherwise identical to general Object properties.
To confirm that fact, try the following sample code
var myArray = ["A", "B", "C"];
for (var i = 0; i < 3; i += 1) {
console.log(myArray.hasOwnProperty(i)); // will print true
}
That is why for..in works with Arrays as well.

Loop Through Array inside Object in Javascript [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Loop through Json object
{
"data": [
{
"name": "Jen",
"id": "1"
},
{
"name": "Steve",
"id": "8"
}
]
}
A server I'm interacting with responds with the above.
I'm trying to loop through itenter code here for the For..in statement.
This is what I'm trying to do:
for (var item in response.data) {
console.log(item.name);
}
This doesn't work.
What went wrong?
Thank you
I GOT IT to work with the following after reading the comment:
for (var item in response.data) {
console.log(response.data[item].name);
}
I was able to get a list of names...
Can someone dissect the response as to why it worked?
data is actually an array (denoted by []), rather than an object so you want a regular for loop rather than a for in.
for (var i = 0; i<response.data.length; i++) {
// use i as an array index
console.log(response.data[i].name);
}
In JavaScript, the for in construct is used for iterating over object properties, but to iterate an array an incremental for loop is typically used.
Check out: Why is using "for...in" with array iteration a bad idea?
For...in iterates through names of the properties of an object. Array items are also considered "properties", so for..in iterates through indexes (which are 0, 1 in your case). As expected when you use response.data[0] you get first element of your array.
for..in iterates over the enumerable properties of an object in no particular order (you may get a different order in different browsers). An array is just a plain object with a special length method and handy methods inherited from Array.prototype (some of which depend on the special length property). There is no restriction on what can be used for a property name, they are not restricted to non-negative integers (noting that where a properly name is not a valid identifier, square bracket notation must be used to access its value).
The indexes of an array are just string property names (i.e. they are just plain object property names) that are non-negative integers, so a for..in loop will iterate over the numeric indexes (again, not necessarily in ascending or descending order) as well as all other enumerable properties, including those on the [[Prototype]] chain. Therefore it is always recommended to include a hasOwnProperty test with for..in unless you want to include inherited enumerable properties.
Because of the above, it is generally much better to iterate over array properties using a counter from 0 to array.length - 1 (since the length is always one bigger than the last index).
To test the "no particular order" statement, try the following in IE and other browser and note the different order:
var a = [];
a[2] = 2;
a[0] = 0;
a[3] = 3;
var b = [];
for (var i in a) b.push(a[i]);
alert(b);

Which takes less memory: a Javascript array or Javascript object?

If I have a Javascript list which will have only numeric keys, which takes less memory?
var array = [];
array[0] = 'hello';
array[5] = 'world';
array[50] = 'foobar';
var obj = {};
obj[0] = 'hello';
obj[5] = 'world';
obj[50] = 'foobar';
I don't know a ton about Javascript engine internals, so...
The reason I ask is because that array, when converted to a string, will have a bunch of undefined's in the middle of it. Are those actually stored in some fashion, or is that just put in at string conversion?
An array is basically an ordered set of values associated with a single variable name.
In your example I think you try to do an associative array, and you should use object, Array is not meant to be used for key/value pairs.
Also the array length is indirecly increased when you assign a value to an index with higher length of the current array length:
var array = new Array();
array[99] = "Test";
// array.length is now 100
Check this detailed article on the subject.
Probably the Javascript array because you can 'only' use numeric key values, where as the object literals provide a space for key values, and even if you use numerical key values, they are probably handled differently than the numerical key values for arrays.
Most likely the reason arrays can't have text-based key values are because they are treated differently than object literals. I'm guessing that because they are probably treated differently, the processing for the array probably is more optimized for numeric key values, were as a object literal is optimized to use strings or numbers as their keys.
JavaScript doesn't implement arrays like other languages so you don't get any performance enhancements inherent of a normal array (memory-wise); in JavaScript an array is very similar to an object; actually, it is essentially an object just with a few extra methods and capabilities (such as a length that updates itself). I'd say neither is quicker.

Categories