views:

413

answers:

5

I know that I can iterate over an object's properties like this:

for (property in object)
{
    // do stuff
}

I also know that the fastest way to iterate over an array in Javascript is to use a decreasing while loop:

var i = myArray.length;
while (i--)
{
    // do stuff fast
}

I'm wondering if there is something similar to a decreasing while loop for iterating over an object's properties.

Edit: just a word about the answers concerned with enumerability - I'm not.

+1  A: 

An object's properties are unordered by definition. The lack of order means that there is no "forwards", and therefore there is no "backwards" either.

NickFitz
I couldn't care less about order. By "similar to decreasing while loop" I meant something analogous in terms of a speed improvement.
Matt Ball
In that case: no.
NickFitz
Actually the object property order is defined -- it's order of addition. Order of properties on the prototype chain becomes more gnarly.
olliej
@olliej - No, the enumeration order of properties is explicitly not defined in the ECMAScript spec. It is implementation dependent and may vary between different objects. An observed order for certain objects in certain browsers should not be relied on universally
Tim Down
I was about to say it was defined in ES5, but it in fact stays undefined in the final April draft (section 12.6.4 The for-in Statement)
Nickolay
@ollie, @Tim Down: worthy of note is the further fact that there is no guarantee that an object's properties will be returned *in the same order on two consecutive iterations*, even though no properties have been either added, removed, or modified. I'm not aware of an implementation that is so obnoxious as to just return things in a different randomly-generated sequence each time, but such an implementation would in fact be in conformance with the ECMAScript spec. Any code that relies on the order of insertion being the order of enumeration is broken; to rely on unspecified behaviour is a bug.
NickFitz
@NickFitz: full agreement here.
Tim Down
+1  A: 

The for/in loop is the best way to enumerate properties of a Javascript object. It should be understood that this will only loop through "enumerable" properties, and in no particular order. Not all properties are enumerable. All properties/methods added programmatically via your own Javascript code will be enumerable, but predefined properties/methods that are inherited (such as toString) are not usually enumerable.

You can check enumerability like so...

var o = new Object();
alert(o.propertyIsEnumerable("toString"));
Josh Stodola
A: 

If you don't know the names of the properties, for..in is a good way to enumerate them. If you do, you're better off with explicit dereference.

DDaviesBrackett
+3  A: 

1) There's no other way to enumerate properties than using for..in (that is until ES5 Object.keys is implemented). Perhaps if you stated your original problem, someone could suggest a way to optimize.

2) I find it hard to believe that the actual enumeration is taking more than whatever you do with the properties in the loop body.

3) You didn't specify what platform you're developing for. The answer would probably depend on it, and the available language features depend on it too. E.g. in SpiderMonkey (Firefox JS interpreter) you could use for each(var x in arr) (docs) if you actually need the values, not the keys. It's faster than for (var i in arr) { var x = arr[i]; ... }.

4) You probably just didn't include it in your snippet, but a faster way to do a for..in iteration is to make sure the variables you use in the loop are declared in the function with the loop, i.e.:

//slower
for (property in object) { /* do stuff */ }

//faster
for (var property in object) { /* do stuff */ }

5) Related to (4): while trying to optimize a Firefox extension I once noticed that extracting a tight loop into a separate function improved its performance (link). (Obviously, it doesn't mean you should always do that!)

Nickolay
You should declare the var outside the for loop so it doesn't try to make a new function-local variable every time.
Eli Grey
What makes you say that? That goes against my intuitive understanding of "var" (which is not "executed" at run-time, but rather scanned-for before a function starts executing) and I don't see anything in the spec about this. So I believe if it is in fact so in some engine, it would be something that can (and should) be fixed in the engine.
Nickolay
A: 

Explicit use of Iterator in JavaScript 1.7+ might be faster or slower. Of course this will only iterate an object's own properties. The catch statement also might be faster with ex instanceof StopIteration replaced with ex === StopIteration.

var obj = {a:1,b:2,c:3,d:4,e:5,f:6},
   iter = new Iterator(obj, true);

while (true) {
    try {
     doSomethingWithProperty(iter.next());
    } catch (ex if (ex instanceof StopIteration)) {
     break;
    }
}
Eli Grey