2
a = {b:'bb',c:'cc',d:'dd'};
$.each(a, function(index){
 // here 'index' is a string variable containing the property name, ie 'b', 'c' or 'd'.
}

I want the integer index of the property - is this possible without using an independent count variable?

user1561108
  • 2,666
  • 9
  • 44
  • 69

2 Answers2

6

You could do this:

Object.keys( a ).forEach(function ( name, index ) {
    var value = a[name];

    name // the property name
    value // the value of that property
    index // the counter
});

This is ES5 API, so you'll need es5-shim for IE8.

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
1

No, it's an object. When you add a new property to a JS object what position is that property supposed to be at? What if you delete a property in the middle and then add it again? What if you merge another object over the original when the merging object had like-named properties in a completely different order in its source code?

You could rig a count and it might work in a lot of cases but there's no guarantee you'd get things in the order you might expect. When order matters, you use an array. When it doesn't and you want to conveniently access things by name you use an object literal. Or you wrap an array in an object that maintains a map to array indeces when they're sorted by writing array sort methods that also sort the key/name map array.

Also, learn for/in loops. There's no reason to use jQuery to iterate a non-jQuery object. At best it will just be marginally slower.

Edit:

Well if you want a count baked in and not an index you can rely on for future reference then I'd just bake my own object type if I had to deal with IE8 since we generally try not to touch the Object constructor prototype (although for normalization to future spec I guess it's might be okay if you can do it without breaking things like for/in loops used on arrays which normally wouldn't iterate the prototype methods).

function IterableCounterObj(objLiteral){ //or perhaps something less painfully named
    this.each = function(iteratorFunc){
        var cnt = 0;
        for(var x in objLiteral){
            cnt++;
            iteratorFunc(x,objLiteral[x],cnt);
        }
    }
}

var a = new IterableCounterObj({b:'bb',c:'cc',d:'dd'});
a.each(function(name,value,count){ console.log(count); });

//too much? Here's the jQuery approach to cruft

var $i = function(objLiteral){
    return new IterableCounterObj(objLiteral);
}

$i({b:'bb',c:'cc',d:'dd'}).each(function(name,value,count){ console.log(count); });
Erik Reppen
  • 4,605
  • 1
  • 22
  • 26
  • 1
    You asked for an index. An index is a type of ordered key. – Erik Reppen Feb 11 '13 at 01:12
  • True :) For my purposes though, which some people seem more interested in than presenting an actual solution, it's just for display purposes and meaningless otherwise. I guess I put count and index in the wrong position. Mea culpa eh? – user1561108 Feb 11 '13 at 01:15
  • @user1561108 No biggie. Not sure what effort any solution could save you over `var cnt = 0;` and then `cnt++;` in the function though. – Erik Reppen Feb 11 '13 at 01:18
  • I'm normally a python person, it just hurts my eyes. – user1561108 Feb 11 '13 at 01:25
  • @user1561108 Python and JS share much in common philosophically if you don't sweat the syntax and some of the design differences. Trust the user for one. Although I tend to think of it more as "yes, more rope please." JS is easy enough to use for simple stuff without learning a lot but has a lot of nice powerful features if you actually take a deeper look under the hood. With proper first-class functions, however, we can include our own batteries that work exactly the way we want them to very quickly and easily. – Erik Reppen Feb 11 '13 at 02:00