I'm parsing JSON and getting an array of objects with javascript. I've been doing this to then append an element for each object:
for(o in obj){ ... }
But I realized that for a certain situation I want to go backwards through the array. So I tried this before the for loop:
obj = obj.reverse();
However this isn't reversing the order of the objects in the array. I could simply put a count variable in the for loop to manually get the reverse, but I'm puzzled as to why reverse doesn't seem to work with object arrays.
There's no such thing as an "object array" in JavaScript. There are Objects, and there are Arrays (which, of course, are also Objects). Objects have properties and the properties are not ordered in any defined way.
In other words, if you've got:
var obj = { a: 1, b: 2, c: 3 };
there's no guarantee that a for ... in loop will visit the properties in the order "a", "b", "c".
Now, if you've got an array of objects like:
var arr = [ { a: 1 }, { b: 2 }, { c: 3 } ];
then that's an ordinary array, and you can reverse it. The .reverse() method mutates the array, so you don't re-assign it. If you do have an array of objects (or a real array of any sort of values), then you should not use for ... in to iterate through it. Use a numeric index.
edit — it's pointed out in a helpful comment that .reverse() does return a reference to the array, so reassigning won't hurt anything.
That's because the for (o in obj) doesn't iterate the array as an array, but as an object. It iterates the properties in the object, which also includes the members in the array, but they are iterated in order of name, not the order that you placed them in the array.
Besides, you are using the reverse method wrong. It reverses the array in place, so don't use the return value:
obj.reverse();
Related
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.
I appreciate there are a few questions here already about how to identify an array. However, I can't find anything regarding identifying an array within an array of objects.
Given the following array:
var pagesArray = [{
category: 'pages1',
pages: [
'firstPage1',
'secondPage1',
'thirdPage1',
'fourthPage1']
}
}];
I have tried to loop through and identify that pages is also an array like so:
EDIT
Actually o in the next example should have been pagesArray but I've left it as is so that the answers make sense.
for(var p in o){
console.log(typeof p);
console.log(p instanceof Array)
console.log(Object.prototype.toString.call(p))
}
The output returned for pages is:
string
false
[object String]
Is there a way to correctly identify that the property is an array or am I misunderstanding something?
For this answer, I assume your are using a for..in loop to iterate over the properties of the object inside pagesArray, that is, pagesArray[0].
for..in iterates over keys, not values. Keys are always strings, so in your loop, p is always a string (here, "categories", or "values"). To get the value associated with a key, use o[p]. You want to test if o["pages"] is an array, not if the string "pages" is an array.
for(var p in o){
var value = o[p];
console.log(typeof value);
console.log(value instanceof Array)
console.log(Object.prototype.toString.call(value))
}
pagesArray[0].pages instanceof Array works fine, though you have an extra curly brace causing a syntax error.
http://jsfiddle.net/vVPCA/
I have an associative array stored in another associative array. I know how to splice a specific value in just a regular array as such:
arr.splice(arr.indexOf('specific'), 1);
I was wondering how one could splice an array such as this:
arr['hello']['world']
EDIT Would this shorten hello['world']['continent']
var hello = {};
hello['world'] = {};
hello['world']['continent'] = "country";
delete hello['world']['continent'];
alert(hello['world']['continent'])
You should be able to just just use the delete keyword.
delete arr["hello"]["world"]
How do I remove objects from a javascript associative array?
Edit, based on other comments:
For the sake of readability, you can also do:
delete arr.hello.world
Since we are really just talking about objects, and not traditional arrays, there is no array length. You can however delete a key from an object.
JavaScript does not have associative arrays.
Use objects:
var x = {
a : 1,
b : 2,
c : {
a : []
}
}
delete x.c.a;
An "associative array" in javascript isn't actually an array, it's just an object that has properties set on it. Foo["Bar"] is the same thing as Foo.Bar. So you can't really talk about slicing or length here.
I have the following js array/object
var x = [1,2,3,4];
x.name = "myArray";
I am using json2.js and I am trying to serialize x in a string.
and all I get is the array:
[1,2,3,4]
is that correct ?
since I can add any property to an array why doesn't json2 handle that ?
what am I missing ?
First of all json2.js ignores properties in the array.
if it had not to ignore them then it would be impossible to have an array in json format which should be easy to eval.
Let's imagine we come out with something like:
[1,2,3,4]{name:'test',anotherProperty:'someValue'}
if the above was valid javascript to create an array and stick two properties then it would be great and we could json-it.
It would be equivalent to do this:
array = [1,2,3,4]
array.name = 'test';
array.anotherProperty = 'someValue';
But it is not and that's the reason why we can not persist into json.
What were you expecting to see? :) I'm not sure what you're trying to do.
x is an array and all you did when you did x.name, you simply set up a property called name for the array object. The name property itself is not added into the array. You can see this in firebug:
The array object has a property called name, but the value of that property is not added to the array itself.
What you want to do is something like this:
var x = {
array: [1, 2, 3, 4],
name: "myArray"
};
Now you have an object called x that has two properties. The array property refers to an array, and the name property refers to the name. x.array will give you the array, and x.name will give you the name.
EDIT
This is in response to your comments. While it is true that arrays can be enriched with properties, think about what it means when you have to serialize that object. What exactly do you want to see when you serialize x? If x is already the array [1, 2, 3, 4], how would you represent it in JSON? You could represent it as:
{ 0: 1,
1: 2,
2: 3,
3: 4,
name: "myArray"
};
But what you now have is no longer an array. Also, the array object itself has a bunch of native properties. How should a JSON serializer handle those?
I think you're mixing up an array as an object and an array as a literal. An array as a literal is just [1, 2, 3, 4]. Now internally, the array as an object presumably has some property that points to the actual value of the array. It also has other properties (like length) and methods that act upon it (like slice).
The JSON serializer is concerned with the value of the object. If x is an array, then the thing that must be serialized is the value of x, which is [1, 2, 3, 4]. The properties of x are entirely different.
If you want to serialize these additional properties, then you would have to write your own serializer that will iterate over the properties of the array and represent everything in a map/associative array. This is the only way; the caveat, as I mentioned before, is that you no longer have an actual array.
The problem is json2 still believes it's an array since x instanceof Array returns true. To fix it, you could create the "array" in a roundabout way:
var x = {
0: 1,
1: 2,
2: 3,
3: 4,
length: 4,
name: 'myArray'
};
The problem with this solution is that none of the array methods will be available on the object. So if you ever need to use pop, push, etc, you'll have to convert it to a real array with Array.prototype.slice.call(x); or if you're byte hungry [].slice.call(x);.
Not sure why you would do it, but a for in loop would get everything
var x = [1,2,3];
x.name = "wtf";
for(var y in x){
console.log(y + ":\t" + x[y]);
}
Produces:
0: 1
1: 2
2: 3
name: wtf
but json2 code will not see it this way, why don't you convert it over to an object?
I have a js 'associative' array, with
array['serial_number'] = 'value'
serial_number and value are strings.
e.g. array['20910930923'] = '20101102'
I sorted it by value, works fine.
Let's say I get back the object 'sorted';
Now I want to access the first KEY of the 'sorted' array.
How do I do it? I can't think I need an iteration with
for (var i in sorted)
and just stop after ther first one...
thanks
edit: just to clarify, I know that js does not support associative arrays (that's why I put it in high commas in the Title).
2021 Update
Since ES6, properties with string keys are enumerated in insertion order. Here's a nice summary. My original answer from 2010 was correct at the time and is preserved below:
Original answer
JavaScript object properties are specified to have no order, much though many people wish it were different. If you need ordering, abandon any attempt to use an object and use an Array instead, either to store name-value objects:
var nameValues = [
{name: '20910930923', value: '20101102'},
{name: 'foo', value: 'bar'}
];
... or as an ordered list of property names to use with your existing object:
var obj = {
'20910930923': '20101102',
'foo': 'bar'
};
var orderedPropertyNames = ['20910930923', 'foo'];
Try this:
// Some assoc list
var offers = {'x':{..some object...}, 'jjj':{...some other object ...}};
// First element (see attribution below)
return offers[Object.keys(offers)[0]];
// Last element (thanks to discussion on finding last element in associative array :)
return offers[Object.keys(offers)[Object.keys(offers).length - 1]];
Actually JavaScript doesn't support associative arrays, so you can't loop through it in an implied order (e.g. you can't access it via the indexer property array[0] won't access the first element in your object). The syntax is what makes it look like it does, but in reality it doesn't. So you have no "Order" to your objects.
http://www.hunlock.com/blogs/Mastering_Javascript_Arrays
Javascript does not have, and does not
support Associative Arrays. However…
All arrays in Javascript are objects
and Javascript's object syntax gives a
basic emulation of an associative
Array. For this reason the example
code above will actually work. Be
warned that this is not a real array
and it has real pitfals if you try to
use it. The 'person' element in the
example becomes part of the Array
object's properties and methods, just
like .length, .sort(), .splice(), and
all the other built-in properties and
methods.
Just thinking off the top of my head, but could you have another array with the key value pairs swapped?
So the answer would be arrayKeyValueReversed['20101102'] = '20910930923';
When you sort the array, use the first item (array[0]) as the key to get the value in the arrayKeyValueReversed.