views:

3462

answers:

7

Consider:

var object = {
    foo:{},
    bar:{},
    baz:{}
}

How would I ...

var first=object[0];
console.log(first);

Obviously that doesn't work because the first index is named "foo", not 0.

console.log(object['foo']);

Works, but I don't know it's named foo. It could be named anything. I just want the first :)

Thanks!

+4  A: 

There is no way to get the first element, seeing as "hashes" (objects) in JavaScript have unordered properties. Your best bet is to store the keys in an array:

var keys = ["foo", "bar", "baz"];

Then use that to get the proper value:

object[keys[0]]
Ben Alpert
+3  A: 

I had the same problem yesterday. I solved it like this:

var obj = {
        foo:{},
        bar:{},
        baz:{}
    },
   first = null,
   key = null;
for (var key in obj) {
    first = obj[key];
    if(typeof(first) !== 'function') {
        break;
    }
}
// first is the first enumerated property, and key it's corresponding key.

Not the most elegant solution, and I am pretty sure that it may yield different results in different browsers (i.e. the specs says that enumeration is not required to enumerate the properties in the same order as they were defined). However, I only had a single property in my object so that was a non-issue. I just needed the first key.

PatrikAkerstrand
+1  A: 

You could do something like this:

var object = {
    foo:{a:'first'},
    bar:{},
    baz:{}
}


function getAttributeByIndex(obj, index){
  var i = 0;
  for (var attr in obj){
    if (index === i){
      return obj[attr];
    }
    i++;
  }
  return null;
}


var first = getAttributeByIndex(object, 0); // returns the value of the
                                            // first (0 index) attribute
                                            // of the object ( {a:'first'} )
CMS
+2  A: 

Thanks for the replies.

I've done this:

var first=false;
for(i in obj){
 if(!first) first=i;
}

I'll consider some of the other solutions if this bites me later :)

Thanks again.

rpflo
I'm already doing this 'for' loop and run some other code on foo, bar, and baz--that's why I don't stop it.
rpflo
Because variables are scoped to functions, you could also do: for (var i in obj) { var first = first || i;}
wombleton
+5  A: 

If the order of the objects is significant, you should revise your JSON schema to store the objects in an array:

[
    {"name":"foo", ...},
    {"name":"bar", ...},
    {"name":"baz", ...}
]

or maybe:

[
    ["foo", {}],
    ["bar", {}],
    ["baz", {}]
]

As Ben Alpert points out, properties of Javascript objects are unordered, and your code is broken if you expect them to enumerate in the same order that they are specified in the object literal—there is no "first" property.

Miles
I've never seen for(i in obj) do things in a different order, are you saying that sometimes for(i in obj) will kick things out in a different order?
rpflo
It's is possible that it will. The specs says that it does not have to be enumerated in a specific order. This pretty much means that that order may change.
PatrikAkerstrand
Most browsers these days do preserve insertion order, but that wasn't always the case; it's not required by the spec, and there were recent versions of Chrome that didn't preserve the insertion order.
Miles
As I got deeper into what I was doing the order of things got more important (I thought I only cared about the first, but I was wrong!) so it was clear to store my objects in an array as you've suggested.
rpflo
If you know that the object has only one element, then you do know the order.
danorton
+2  A: 

they're not really ordered, but you can do:

var first;
for (var i in obj) {
    if (obj.hasOwnProperty(i) && typeof(first) !== 'function') {
        first = obj[i];
        break;
    }
}

the .hasOwnProperty() is important to ignore prototyped objects.

Luke Schafer
+3  A: 

If you want something concise try:

for (first in obj) break;

alert(first);
Patrick Hayes