20

I'm using a javascript associative array (arr) and am using this method to loop through it.

for(var i in arr) {
    var value = arr[i];
    alert(i =") "+ value);
}

The problem is that the order of the items is important to me, and it needs to loop through from last to first, rather than first to last as it currently does.

Is there a way to do this?

Urbycoz
  • 7,247
  • 20
  • 70
  • 108

4 Answers4

47

Four things:

  1. JavaScript has arrays (integer-indexed [see comments below]) and objects (string-indexed). What you would call an associative array in another language is called an object in JS.

  2. You shouldn't use for in to loop through a JS array.

  3. If you're looping through an object, use: hasOwnProperty.

  4. JavaScript doesn't guarantee the order of keys in an object. If you care about order, use an array instead.

If you're using a normal array, do this:

for (var i = arr.length - 1; i >= 0; i--) {
    //do something with arr[i]
}
Community
  • 1
  • 1
Skilldrick
  • 69,215
  • 34
  • 177
  • 229
  • +1, I deleted my answer in favour of this one. Chrome is one browser that differs from the others with regards to enumeration order - http://code.google.com/p/v8/issues/detail?id=164. – Andy E Feb 10 '11 at 11:35
  • JS doesn't have any integer property names, even in arrays, so your first point is slightly misleading. – Tim Down Feb 10 '11 at 11:44
  • 1
    @Tim You're right, but to all (most) intents and purposes they are integer-indexed - the fact that they're strings under the hood is an implementation detail. Especially when explaining this to someone who talks about "associative arrays" in JavaScript it's useful to put stuff in terms they'd understand. Is that fair? – Skilldrick Feb 10 '11 at 12:33
  • @Skilldrick: I think that's fair enough, I just wanted there to be a note to explain why `["foo"]["0"]` evaluates to "foo". I've upvoted already. – Tim Down Feb 10 '11 at 13:36
  • @Tim Thanks. It took me a couple of read-throughs to work out what that snippet was doing! I've put a note to look at the comments :) – Skilldrick Feb 10 '11 at 13:43
  • @Skilldrick: Yeah, maybe that's too Resigian / clever-clever. `var a = ["foo"]; alert(a["0"]); // "foo"` might have been clearer. – Tim Down Feb 10 '11 at 13:46
  • @Urbycoz - no problem. Objects and arrays in JS can be a bit confusing when you're used to other languages. – Skilldrick Feb 10 '11 at 15:53
15

Warning: this answer is ancient.

If you're here for a quick fix, kindly refer to the much better answer below.

Original answer retained, because reasons. See comments.


Using a temporary array holding the keys in reverse order:

var keys = new Array();

for (var k in arr) {
    keys.unshift(k);
}

for (var c = keys.length, n = 0; n < c; n++) {
   alert(arr[keys[n]]);
}
Linus Kleen
  • 33,871
  • 11
  • 91
  • 99
  • @Urbycoz: but you're not guaranteed the same order in all browsers - see the other answers below. – Andy E Feb 10 '11 at 11:26
  • 3
    @Urbycoz You might want to think about unaccepting this answer and accept Skilldricks's instead. I'd like to delete mine and I can't because you accepted it (my past me says "Thank you"). However, Skilldrick's is more accurate. Thanks. – Linus Kleen May 21 '13 at 20:14
  • Clever !? No way. this is utter garbage where the obvious simple answer would be the one below: reverted for loop. – RickyA Nov 10 '16 at 10:54
  • ppl hate but this answer helps. Just keep in mind that associative array = js object. – Roberto Sepúlveda Aug 03 '20 at 13:51
3

For a normal array, I would have done this:

var i = arr.length;
while (i--) {
    var value = arr[i];
    alert(i =") "+ value);
}

This is faster than a "for" loop.

http://blogs.oracle.com/greimer/entry/best_way_to_code_a

Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
  • When you say this is faster than a `for` loop, you mean to say that it's faster when doing a reverse iteration specifically? – Jonathan Feb 03 '16 at 17:26
  • 1
    `for in` for an array as in the OP's example - in some browsers it was also faster than the negative for loop - but I have not tested this in some time (note the 5 year old post) – Mark Schultheiss Feb 03 '16 at 17:41
  • 1
    Note that the negative iteration in javascript (this or the for) gives the parser a chance to enhance performance given the length is known prior - so it MIGHT in-line or otherwise optimize that. There is a PHD dissertation somewhere out there re: parsed languages have the potential to exceed compiled languages performance such as C, C++ etc. but the reference escapes me that has to do with this factor. – Mark Schultheiss Feb 03 '16 at 17:46
  • Thanks for the info, would be a great read if you did happen to come across it again :) – Jonathan Feb 04 '16 at 09:23
2

In modern browsers you can now use Object.keys to get your array of properties and step through it in reverse order, allowing you to skip the preliminary key collection loop.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

var keys = Object.keys(subject);
for (var i = keys.length-1; i >= 0; i--) {
    var k = keys[i],
        v = subject[k];
    console.log(k+":",v);
}
Ben Thielker
  • 4,104
  • 4
  • 21
  • 20
  • OP talks about arrays not objects/maps. This answer does not add anything compared to `Skilldrick'es`. – RickyA Nov 10 '16 at 10:56
  • @RickyA: OP does in fact talk about iterating an Object. Skilldrick's response indicates an understanding that OP is referring to an Object via incorrect terminology, but proceeds to respond as if the question were about iterating an Array. – Ben Thielker Nov 15 '16 at 20:50