19
var obj = { 'a' : 'apple', 'b' : 'banana', 'c' : 'carrot' }

If I do a

for (var key in obj) {
  console.log( key + ' has a value ' + obj[key] );
}

It will look through all the values in obj. If I have a much larger object, how do I know if I am on the last iteration of that for loop?

I realize that key value pairs aren't really organized in order, but I need to accomplish something in the very last iteration of this loop and don't know how.

2

6 Answers 6

43

don't use for (key in obj), it will iterate over all enumerable properties including prototype properties, and can lead to amazingly horrible things. Modern JS has a special function for getting only the relevant keys out of an object, using Object.keys(...), so if you use var keys = Object.keys(obj) to get the list of keys as an array, you can then iterate over that:

// blind iteration
Object.keys(obj).forEach(function(key, i) {
  var value = obj[key];
  // do what you need to here, with index i as position information.
  // Note that you cannot break out of this iteration, although you
  // can of course use ".some()" rather than ".forEach()" for that.
});

// indexed iteration
for(var keys = Object.keys(obj), i = 0, end = keys.length; i < end; i++) {
  var key = keys[i], value = obj[key];
  // do what you need to here, with index i as position information,
  // using "break" if you need to cut the iteration short.
});

or select its last element immediately

var keys = Object.keys(obj);
var last = keys[keys.length-1];

or using a slice:

var keys = Object.keys(obj);
var last = keys.slice(-1)[0];

or using a shift (but that's a destructive operation, so we're not caching the keys because the shift turns it into "not all the keys anymore"):

var last = Object.keys(obj).shift();

2021 edit

There is now also the Object.entries function, which gets you key/value pairs in one go:

Object.entries(obj).forEach(([key, value]) => {
  console.log(`key "${key}" points to:`, value):
});
Sign up to request clarification or add additional context in comments.

7 Comments

Exactly what I was going to suggest.
Why should a Object.keys(obj) be better then a for( key in obj) with hasOwnProperty (I know the hasOwnProperty is not in the question) ? Object.keys will create a new object holding the keys.
@t.niese Obj.keys() = ECMAScript 5.1
@t.niese you pretty much answered your own question. A single API call that generates the data required is better than a blind iteration that then requires an extra calls for each value found to check whether it's actually the correct value. Object.keys might generate a new array, but the time required to do that is far less than the time required to call that .hasOwnProperty check for each attribute, and you're not going to see a spike in your memory profile from the arrays created by Object.keys under for-webpage conditions (for-custom-engines conditions are a different beast)
@Mike'Pomax'Kamermans ok yes, just did a little test and it performs way better then the last time I tested it. Engines got better in creating the list at once and probably also handles it in a way that they only do a real memory allocation if array is modified, at least V8 seems to do a really great job here.
|
4

You could loop through all of them and save the last one in a variable.

var lastItem = null;
for(var key in obj) {
  console.log( key + ' has a value ' + obj[key] );
  lastItem = key;
}
// now the last iteration's key is in lastItem
console.log('the last key ' + lastItem + ' has a value ' + obj[lastItem]);

Also, because of how JavaScript works the key is also in your loop's key variable, so the extra variable is not even needed.

for(var key in obj) {
  console.log( key + ' has a value ' + obj[key] );
}
// now the last iteration's key is in key
console.log('the last key ' + key + ' has a value ' + obj[key]);

2 Comments

Smart! I didn't know this.
@ggorlen Thanks for the notification. (I guess you could have just as easily fixed the post yourself.)
3

just shorter

var last = (last=Object.keys(json))[last.length-1];

Comments

0

You could put the logic for the last item outside the loop:

var last_item = null;
for (var key in obj) {
  last_item = key;
}
console.log(last_item);

Comments

-1

You could push all of the keys/values into a a empty array variable that you created. Then, access the last element in the array using array.length-1.

1 Comment

This is a huge waste of memory. If you have an object with a million entries, you hit the heap to create a million-element array, then toss the whole thing to the garbage collector immediately just to get one element from it. Other answers show better approaches that use O(1) memory without sacrificing readability.
-3
for(var x=0 ; x<Object.keys(obj).length ; x++)
{
     if(x==Object.keys(obj).length-1) // code for the last iteration

}

Or could use Object.size(obj)

2 Comments

I don't see why not. Trivial issue, there's always the Object.size(obj)
This unnecessarily calls Object.keys twice for every element of the array! One call is all you need, as shown in other answers, O(n) instead of O(n*n).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.