0

Javascript doesn't have a general object iterator, to allow something like:

foo.iterate (function (key, value) {
    console.log ("key->" + key + " value->" + value);
});

Seems convenient and trivial to implement. Is something like this built in to any popular libraries? I don't want to reinvent the wheel, and if do something like this would like to follow naming (and semantic) conventions for any existing method.

So does a general iterator like this exist somewhere?

added: I've been tinkering around and added an iterator function to Object.prototype. This slowed down the for loop by a factor of about 20! I wasn't even calling the new iterator method, just adding it to Object's prototype greatly slowed down for loops. I'm assuming this negates an optimization in Chrome. This would explain why none of these libraries mentioned add an iteration method to Object.

2
  • 1
    jquery $.each does that.. Commented Dec 13, 2013 at 23:08
  • Are you going to pick an answer? Commented Dec 16, 2013 at 17:09

4 Answers 4

4

It doesn't, but here's a way to do it without libraries or extra functions (other than for..in loop):

Object.keys(foo).forEach(function(key){
  console.log(this[key]);
}, foo);
Sign up to request clarification or add additional context in comments.

5 Comments

+1, in modern JavaScript - this is the most correct approach. Also - JavaScript does have a way to explicitly do that - the for in loop (or better, for of loop)
Object.keys() will create a new object, right? Might as well avoid that if it's easy to avoid.
Actually, Object.keys() will return an array of keys from the object foo. For example, if foo = {bar:1, baz:2}, then Object.keys(foo) would return ['bar', 'baz'].
@BenjaminGruenbaum why you don't provide an answer showing how to use the for of syntax? I can't seem to get it working in my console (Firefox).
In my crude benchmarks, using Object.keys() is about 10 times slower than iterating with for() on Chrome Mac.
2

You can use for-in, but you need to add extra code to distinguish properties of the object itself from those inherited from a prototype:

Object.prototype.iterate = function(callback) {
    for (var key in this) {
        if (this.hasOwnProperty(key)) {
             callback(key, this[key]);
        }
    }
}

Every object now has an iterate() method since we've attached this function to the Object prototype. Now, you can use the code example from the OP to iterate over the properties of the object foo.

Note: there are NO "classes" in Javascript, and functions are first class data types. So, any functions or "methods" added to the object will be iterated over using this function as well.

Comments

1

Why not a simple for in loop ?

for(var key in obj) {
     console.log ("key->" + key + " value->" + obj[key]);
}

2 Comments

This is the cleanest way to do what I want. Just would like it wrapped up with a bow and be able to have the value supplied in an arg.
@obelia, remember to check for obj.hasOwnProperty() as in Barmar's answer. Otherwise, you'll also see inherited properties such as length that come from objects prototype chain. For detailed discussion see hasOwnProperty on MDN
1

Yes! Most popular libraries implement some form of this. Here's a few examples:

  1. jQuery.each(). Here's an example:

    $.each([ 52, 97 ], function( index, value ) { alert( index + ": " + value ); });

  2. Underscore _.each(). Here's an example of this one:

    _.each([1, 2, 3], alert);

  3. Dojo Toolkit's forEach()

  4. Apparently, Javascript 1.7 has an iterator built in

  5. See also the Prototype framework's Enumerable, albeit a bit dated.

I would highly recommend underscore for it's wide variety of utility methods to make manipulating JavaScript objects and arrays easy, even for more sophisticated operations. This has the advantage of working client and server side without having lots of DOM manipulation functionality built-in like jQuery, Dojo, and Prototype.

If you're looking to implement a simple version of each() for arrays, checkout the functional programming chapter in Eloquent Javascript and his implementation:

function forEach(array, action) {
  for (var i = 0; i < array.length; i++)
    action(array[i]);
}

forEach(["Wampeter", "Foma", "Granfalloon"], print);

3 Comments

Underscore's _.each() does what I want. I would expect that to be more cleanly implemented as an Object method (and Array method).
Great! Glad I could point you in the right direction. Some JavaScript developers don't like to augment native JavaScript types (such as Array and Object) with additional functionality since it could be confusing to figure what is baked into the language and what has been added. I guess it's more a personal preference than a black and white sort of decision.
@obelia, I see your OP mentioned using foo.each(...). It's a bit dated now, but the client side MVC framework Backbone.js builds on Underscore to do exactly this sort of operation on it's models.

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.