dean.edwards.name/weblog/2006/07/enum/

Enumerating JavaScript Objects

Enumeration lies at the heart of DOM Scripting:

var lists = document.getElementsByTagName("UL");
for (var i = 0; i < lists.length; i++) {
	lists[i].className = "menu";
}

for (var i = 0; i < array.length; i++) {
	print(array[i]);
}

for (var key in object) {
	print(object[key]);
}

Us JavaScripters are forever writing loops like these. To ease the strain on our keyboards Mozilla recently introduced a handy forEach method for arrays:

array.forEach(print);

If you don’t understand the code above then go and read the documentation.

That’s fine for arrays but what about DOM node lists? That’s where most of our loop writing is concentrated. Fortunately, the clever Mozilla developers provide generic array methods to help us:

var lists = document.getElementsByTagName("UL");
Array.forEach(lists, function(list) {
	list.className = "menu";
});

Cool huh? The Array.forEach method treats any object passed to it as if it were an array. So long as that object has a length property then we are OK.

We can easily implement this method for non-Mozilla browsers:

// array-like enumeration
if (!Array.forEach) { // mozilla already supports this
	Array.forEach = function(object, block, context) {
		for (var i = 0; i < object.length; i++) {
			block.call(context, object[i], i, object);
		}
	};
}

I’ve been using this technique for enumeration quite a lot recently and I decided to extend the idea:

// generic enumeration
Function.prototype.forEach = function(object, block, context) {
	for (var key in object) {
		if (typeof this.prototype[key] == "undefined") {
			block.call(context, object[key], key, object);
		}
	}
};

// globally resolve forEach enumeration
var forEach = function(object, block, context) {
	if (object) {
		var resolve = Object; // default
		if (object instanceof Function) {
			// functions have a "length" property
			resolve = Function;
		} else if (object.forEach instanceof Function) {
			// the object implements a custom forEach method so use that
			object.forEach(block, context);
			return;
		} else if (typeof object.length == "number") {
			// the object is array-like
			resolve = Array;
		}
		resolve.forEach(object, block, context);
	}
};

This allows me to write loops without knowing what kind of object I’m dealing with:

function printAll() {
	forEach (arguments, function(object) {
		forEach (object, print); 
	});
};
// or
forEach (document.links, function(link) {
	link.className = "super-link";
});
// or
forEach ([1, 2, 3], print);
forEach ({a: 1, b: 2, c: 3}}, print);
// etc

Explanation

The global forEach function allows us to enumerate any object according to its type. If the object is array-like (has a length property) then we enumerate it like an array. All other objects are enumerated using the standard for var x in y mechanism.

When enumerating over objects, the discovered keys are compared against Object.prototype. If the key is defined on the Object object then it is not enumerated. That means that you cannot enumerate the built-in methods like toString and valueOf.

The global forEach function will delegate the enumeration of functions to Function.forEach. So, if you choose to enumerate over a Function object you will skip the built-in methods there too.

The Kick-Ass Bit

Although I’ve defined a forEach method on Function.prototype this is never called by the global forEach function (except when you are enumerating functions).

I’ve provided this as a bonus feature. :-) Basically, by calling the forEach method on a function you can enumerate an object and compare the keys with that function’s prototype. That means that you will only enumerate custom properties of the object. An example is required:

// create a class
function Person(name, age) {
	this.name = name || "";
	this.age = age || 0;
};
Person.prototype = new Person;

// instantiate the class
var fred = new Person("Fred", 38);

// add some custom properties
fred.language = "English";
fred.wife = "Wilma";

Enumerate using the standard forEach method:

forEach (fred, print);
// => name: Fred
// => age: 38
// => language: English
// => wife: Wilma

Enumerate using the Person.forEach method:

Person.forEach (fred, print);
// => language: English
// => wife: Wilma

Note that the properties defined on the prototype are not enumerated in the second example.

Conclusion

I’m totally in love with this technique. I now use it all the time. It makes my code more readable and I feel safer enumerating over objects on different platforms.

It also saves on typing. ;-)

Download: forEach.js

Comments (83)

Leave a comment

I love this. Takes care of one of the biggest annoyances of dealing with objects in JS.

2 things:

  1. It is very tempting to implement forEach on all kinds of objects. But it is not always clear what it iterates over. F.e. String.forEach could enumerate over characters, words or lines. It is better to implement methods that return arrays, and then iterate over the array. The method name then makes it clear what is iterated over, and your code is more generic, because you can do more with arrays than just iterating.
  2. typeof this.prototype[key] == "undefined" can be written as this.hasOwnProperty(key)

Very handy with jQuery :-)

@sjoerd: strings are array-like Objects and contain characters. If you whant to iterate over the words or lines, use split(): forEach("string with words".split(' '), function() {...});

In the name of all javascript-code-maintainers in the world who have had to figure out what other people’s “clever” code did, I would like to offer you a swift kick in the privates.

Thank you.

  • Comment by: David Barker
  • Posted:

Thank you.

  • Comment by: -dean
  • Posted:

@Sjoerd –

  1. What I like about this notation is that it places the iteration statement (forEach) on the left. When enumerating arrays with map etc the iteration statments end up on the right and the code becomes difficult to read. The temptation is to chain your iteration methods and you end up with unreadable code.
  2. hasOwnProperty is not implemented in IE5.0. It would be a shame to exclude that browser for the sake of one line of code.

Good point about the String object. Maybe I’ll implement Christof’s split idea to support iteration of character data.

  • Comment by: -dean
  • Posted:

@Christof – I just added this:

// character enumeration
String.forEach = function(string, block, context) {
	Array.forEach(string.split(""), function(chr, index) {
		block.call(context, chr, index, string);
	});
};

:-)

  • Comment by: -dean
  • Posted:

typeof this.prototype[key] == "undefined" || this.prototype[key] !== object[key] is a better approximation of hasOwnProperty. Although there is still the obvious edge-case and maybe you prefer the current behaviour.

  • Comment by: Daniel James
  • Posted:
  1. Awesome.
  2. Suggestion: how about extending awesomeness to be consistent with all of JS1.6′s additions? (every, filter, map, some).
  • Comment by: Brito
  • Posted:

How about making the context default to the object? that could save some keystrokes. block.call(context || object, object[key], key, object);

  • Comment by: Brito
  • Posted:

@Brito – I’ve written support for every, map, etc but it’s in a separate library which I haven’t yet released. I published this code because it was small and self-contained. And cool.

I like your idea of defaulting to the current object. Let me ponder that…

  • Comment by: -dean
  • Posted:

@Dean I don’t think defaulting “this” to the current object is such a good idea.

It differs from Firefoxes native behaviour, and the object is also available anyway, as arguments[2] within the block function.

  • Comment by: Már
  • Posted:

@Már – you are probably right. I seem to remember going through that thought cycle a while back and gave up on the idea.

  • Comment by: -dean
  • Posted:

Isn’t it true that

for (var i=0, obj=null; obj=object[i]; i++) {
   block.call(context, obj, i, object);
}

is faster than

for (var i = 0; i < object.length; i++) {
   block.call(context, object[i], i, object);
}

because in the former, the “object.length” attribute is evaluated for each iteration, and counted every time it is accessed? (That might just be for arrays, or HTMLCollections, or something. But I’m sure I’ve heard this.)

Awesome, Dean.

You could take this a step further and try to back-hack JavaScript 1.7′s iterators, the ultimate in polymorphism. You’d have a wrapper object that’d respond to foo.next() calls, then throw an exception when it’s spent, etc.

Probably overkill, I admit. But I’ve been playing with the new JS 1.7 stuff and it’s making me salivate.

@Andrew – foo.next() requires that you throw a StopIteraton error in order to terminate the loop. I implemented something similar and ended up hating it. It is really hard to debug JavaScript when you are throwing errors in nested closures that you are passing around. I still have one throw StopIteration statement left in my library, it is nicely contained but I still want to get rid of it. ;-)

  • Comment by: -dean
  • Posted:

Andrea Giammarchi also wrote JSL Javascript Standard Library

that have lots of useful prototypes to support the new methods in ECMA that IE(but not only) doesn’t implement

take a look.

P.s. Dean, grrrreat Work!

I lost a piece of comment , I was mean: “Andrea Giammarchi also wrote Array.forEach in JSL: Javascript Standard Library”, sorry for the mistake.

@Anthony Lieuallen : you are right, but the faster method is to write a while with a decrement variable because in javascript –i is a lot faster of i++ and a while is a lot faster that a for loop.

@Anthony, you can’t do that as it’ll stop early if an array element is false or null.

@Kentaromiura, the speed up would be negligible compared to the time required for fetching the array element and calling the callback. And you’d have to either fetch the elements backwards (which is probably wrong and can be a lot slower, DOM methods are often optimized for forward iteration) or perform some arithmetic to get the correct element (which would take longer than the time saved). Premature optimization etc.

But, it’s actually better to write: for (var i = 0, length = object.length; i < length; ++i). Not because it’s faster but because it’s how forEach is defined (although, it’s probably not a great idea to rely on such subtlties).

  • Comment by: Daniel James
  • Posted:

#19: ok, I wasn’t refer to this case when I say the –i, but a while is still faster than a for.

for (var i = 0, length = object.length; i < length; ++i)

is a good optimization, but no so good as

var i=0,length=object.length; while(i<length){ .. i++; }

;)

Optimizations are good things once you have completed something. If you argue that a while is more verbose that a for, when you use a good compressor(packer) your code is not verbose anymore..

There’s a great example of this in the Optimizing JavaScript for Execution Speed chapter at websiteoptimisation.com

Here’s the Flipped Loop with Optimized Reverse Count

function loopDoWhileReverse3() {
var i=iter;
if (i>0) { // make sure i is positive here
    do 
    {
        // do something here
    }
    while (--i); // i must be greater than 0 here
    }
}
  • Comment by: Paul Wilkins
  • Posted:

@Anthony Lieuallen:

for (var i=0, obj=null; obj=object[i]; i++) {
   block.call(context, obj, i, object);
}

doesn’t work in this case:

object = [42,16,0,false,true,'Hello World!'];
for (var i=0, obj=null; obj=object[i]; i++) {
   block.call(context, obj, i, object);
}

If you care about the speed try

var l = object.length;
do {
   block.call(context, object[l], l, object);
} while (--l)

In case you want really fast loops, unroll them.

But I guess that the function-call is a lot slower than everything that is done for managing the loops. I wouldn’t expect too much performance gain here.

@Everyone – looping backwards is not an option.

  • Comment by: -dean
  • Posted:

It’s all my fault, I’m a sort of Optimization Maniac because in my 486 every single optimization is a big improvement ;) so I’ve suggested the while solution instead of for ;) sorry for beginning this disgression ;p

It got hidden in all the talk about optimization, but I wasn’t suggesting storing the length as an optimization but because it’s the right thing to do. From the mozilla documentation:

The range of elements processed by forEach is set before the first invocation of callback. Elements which are appended to the array after the call to forEach begins will not be visited by callback. If existing elements of the array are changed, or deleted, their value as passed to callback will be the value at the time forEach visits them; elements that are deleted will have the value undefined.

  • Comment by: Daniel
  • Posted:

@Daniel – ah OK. I thought I’d tested that. My mistake. I’ll update the code…

  • Comment by: -dean
  • Posted:

doesn’t work in this case:

object = [42,16,0,false,true,'Hello World!']; for (var i=0, obj=null; obj=object[i]; i++) { block.call(context, obj, i, object); } Why? I don’t understand :(

  • Comment by: Alex
  • Posted:

@Alex – the “obj=object[i]” part of for (var i=0, obj=null; obj=object[i]; i++) is evaluated as a conditional statement, and the for-loop is broken as soon as it returns false.

Incidentally both object[2] (0) and object[3] (false) are bound to make the for-condition fail and thus leave the rest of the array items unprocessed.

  • Comment by: Már
  • Posted:

Hello, could anyone say is it any usefull for those who use prototype.js with it’s each etc.? Thanks

  • Comment by: Mark
  • Posted:

Dean,

Do you know of anything about the speed implications of instanceof in javascript? I use javascript quite a bit but have never looked into instanceof. I know in school we were always told to never use instanceof. We should always enumerate _whatever_ because instanceof is so slow. In this case however you are using instanceof for enumeration, (and what you have done here is really sweet) so I would like to know just how bad instanceof is.

Thanks, Wesley Walser

@Wesley – in pure OO terms you shouldn’t use instanceof as type-checking is frowned upon. As far as JavaScript goes I am not aware of any speed issues. In this case, it only called once to determine which forEach method to use. It is not called inside any loops.

  • Comment by: -dean
  • Posted:

damn dean, good sh*t, when are you coming out with a book?

  • Comment by: apl
  • Posted:

[...] Previous post: ← Enumerating JavaScript Objects [...]

damn dean, good sh*t, when are you coming out with a book?

Who reads books when you’ve got Google?

  • Comment by: -dean
  • Posted:

[...] Enumerating JavaScript Objects
LINK:http://dean.edwards.name/weblog/2006/07/enum/ [...]

@Dean – I’ve been thinking about this and the the bit where you extend Function.prototype bugs me a little bit. It seems kind of out of place next to Array.forEach and String.forEach.

Could you explain to me why you chose against simply calling it Object.forEach.

It seems to me that it would allow you to simplify the generic (global) forEach function quite a bit.

Is the ability to call objectInstance.forEach the main reason for your decision?

  • Comment by: Már
  • Posted:

@Dean – ok, sorry, I get it now why you go for the Function.prototype.forEach (my bad).

However, the thing that still confuses me is that a basic Object.forEach seems missing from the example. Is that intentional?

  • Comment by: Már
  • Posted:

I did some testing this morning, and finally realized the full implications of extending Function.prototype.

Fucking. Awesome. :-)

  • Comment by: Már
  • Posted:

@Már – Extending Function.prototype means that I can identify custom properties of an object. It also means that you can extend native objects and have safe enumeration. Yep, fucking. Awesome. :-)

  • Comment by: -dean
  • Posted:

As far as execution speed is concerned, I’ve found that Array.forEach is *much* slower than equivalent non-1.5 code. Same with all other Array shorthands introduced in 1.5.

  • Comment by: Nikola Klaric
  • Posted:

typeof this.prototype[key] == “undefined”

I just wondering why this idiom is used all around over shorter and more explicit form: !(key in this.prototype)

VS

@Nikola – Really? That is surprising. I just assumed that built-in methods were faster. :-?

@Valery – we check for undefined because values of false or zero would both fail your test.

  • Comment by: -dean
  • Posted:

Dean,

Are you sure? You are checking for existence of key, hence operator “in” is better, IMO.

Do not confuse:

!(key in this.prototype)

and

!(this.prototype[key])

(I used the first form, you comment the second one ;)

VS

@Valery – My mistake. I misread your comment. :-) Yes, you could use that notation too but there are a couple of older platforms where it doesn’t work so typeof is safer.

  • Comment by: -dean
  • Posted:

@Dean – sadly, yes. I’ve been toying around with some large array operations recently (.forEach, .some, .every on 10.000+ elements) and tried the new Array functions inside an 1.5 extension, speed decrease by more than 50%. Even on the simplest iterations. Either it’s a bug, or the builtins do some implicit type evaluations that end up being quite expensive.

By the way, I’d be glad if you could cover the new Destructuring Assignment in JS 1.7 after the FF 2.0 release. I’ve found that even many Python programmers don’t know how to use it properly, or even know that it exists.

  • Comment by: Nikola Klaric
  • Posted:

@Nikola Klaric: I guess you don’t do an extra function call inside the loop in your non JS 1.5 code. To call the callback function the JS-interpreter has to generate a new context for local variables, execute that function and then find out if the context can be freed or if it contains values that are still referenced. That is rather expensive compared to just entering the block of a for-loop.

@Christof: +1 Seems to be an issue: cost of executing “for” block N times is much lower then cost of N function invocations.

@Nikola: Just wondering how much it takes to process 10.000+ elements. I have (not the most complex) use case where it takes 3 second for IE to process less then 1000 elements (grouping of elements by attribute, original source is array, target is object with array properties).

VS

Yep! That’s a cool way to iterate!

(And extending Function.prototype is useful for a lot of things :-D.)

@Dean: I almost never read books about programming any more, though I’ve seen that The Man in Blue and {ppk} released one each recently, so I might order those two. (If you wrote a book I might be tempted to read that one too.)

What about: for (var i in x) (function() { … }).apply(x[i]);

  • Comment by: Konstantin
  • Posted:

What about it?

  • Comment by: -dean
  • Posted:

@dean, it might be worth noting excplicitly in the source code that the order is important. First you must check for the existence of and define Array.forEach and only then define Function.prototype.forEach.

I had already got Array.forEach in my toolkit, and after reading this blog-entry decided to add your Function.prototype.forEach to the mix. I inadvertedly placed it above my old Array.forEach and then things started to behave strangely in Internet Explorer.

It took me a while to figure out where I’d gone wrong. :-)

  • Comment by: Már
  • Posted:

@Már – If you are smart enough to implement your own Array.forEach then you are smart enough to work out the rest. Just like you did. ;-)

  • Comment by: -dean
  • Posted:

Any particular reason why Function.prototype is extended with forEach but String.prototype isn’t?

  • Comment by: MrBester
  • Posted:

@MrBester – I think there is a good reason — I just can’t remember what I was thinking at the time. :-) For completeness it should probably be implemented on both interfaces.

  • Comment by: -dean
  • Posted:

[...] Só complementando o post achei um exemplo bacana de prototipação de um forEach no Javascript. O mozilla já incorporou um objeto Array.forEach mas enquanto isso não abrange todos tá aí a função prontinha AQUI [...]

Regarding the Array forEach implementation for non-Mozilla browsers:

One also needs to provide an Array.prototype.forEach implementation like the following for a Mozilla compatible behaviour:

Array.prototype.forEach = function(callback, thisObj) {
    for (var i = 0,len = this.length; i < len; i++)
       callback.call(thisObj, this[i], i, this);
};

Otherwise code like [1, 2, 3].forEach(print) will lead to an “Object doesn’t support this property or method” (or so) error.

(If only the global forEach implementation is used all the time the Array.forEach function is sufficient.)

  • Comment by: Udo
  • Posted:

Very nice, especially the check for the over-riding custom for each. Does this code make prototyping array, even object are of little concern?
Regarding speed here is a page to test the speed of functions I just put up: jsSpeedTester. Enjoy and thanks again for some head scatching Dean. :)

  • Comment by: richard m.
  • Posted:

@richard – Yes. Using this technique you can extend native JavaScript objects. See my subsequent post.

  • Comment by: -dean
  • Posted:

Thanks Dean. I do believe that this code can find a good home in my library :) Can’t believe that I have not stumbled across your site before now.

Dean amazing piece of work I added a small number enumeration to the code a little while back and I modified the character enumeration. But I got a small question.

When doing the following

// number enumeration
Number.forEach = function(number, block, context){
    for(var i=1;i <=number;i++){
        block.call(context, i, number);
    }
}

This is pretty straight forward but I wanted to have the “Kick Ass” touch you described at the bottom of original post. Then I did this

// number enumeration
Number.prototype.forEach = function(block){
    for(var i = 0;i <= this;i++){
        block(i, this);
    }
}

// character enumeration
String.prototype.forEach = function(block) {
    var _this = this;
	Array.forEach(this.split(""), function(chr, index) {
		block(chr, index, _this);
	});
};

This will let you do things like ‘hello’.forEach(print), but for the number you will have to do var ten = 10; ten.forEach(print) as well as forEach(10, print) and forEach(‘hello’, print). My initial idea was to produce something like 10.forEach(print) but couldn’t do it what I got get close.

Does this make sense to you guy’s or am I doing something competely wrong? Is it ok to do block() instead of block.call() inside of the String and Number method?

the modified forEach.js file for easier reading

  • Comment by: Laurent Muchacho
  • Posted:

@Laurent – To be compatible with other forEach functions you should also take a context argument. If you want to call forEach on a number simply wrap the number in parentheses:

(10).forEach(print);

I like the idea of forEach on numbers, it is a good way to loop a certain number of times although the passed arguments are of little value.

  • Comment by: -dean
  • Posted:

[...] Dean Edwards recently described a pretty cool technique for enumerating javascript objects, but (currently) it’s not appropriate for sparse arrays. In case you’re unfamiliar with sparse arrays (or I’m using the wrong term), in the language of the Mozilla documentation for Array.forEach, a sparse array is one that’s not “dense”. For example: [...]

[...] Javascript’s new forEach() function. Thanks to Dean Edwards, there is a cross browser solution, that is extremely simple to use. There are some other new functions as well that I haven’t explored yet, but they are worth noting. [...]

[...] The base2 core library is also quite useful in its own way. It includes things like my Base class and enumeration methods. I’ll document this library sometime in the future (it’s only little). For the time being I am only supporting the base2.DOM module and even then only if you are using the bind() method that I’ve demonstrated here. [...]

That is really awesome. I needed something like forEach a thousand times working with JS. PHP has a similar way of handling arrays too and it is much more simple. Nice work!

Dean is there anyway to break out of the forEach? I wanted to use it for searching for a value in an array of objects but could not find a way to get it to “break” out of the loop. Had to revert to a for loop instead in the mean time. Not had enough tea to ponder it over enough properly yet.

@Pete – You can throw to break out of a loop. Like this:

if (typeof StopIteration == "undefined") {
	StopIteration = new Error("StopIteration");
}

try {
	forEach (array, function(value) {
		if (value == "should break here") {
			throw StopIteration;
		}
	});
} catch (error) {
	if (error != StopIteration) throw error;
}
  • Comment by: -dean
  • Posted:

[...] Dean Edwards: Enumerating JavaScript Objects nifty js object iteration (tags: code tutorial usability javascript howto programming prototype reference ajax) [...]

I found this bit of code today, and well, pretty nice stuff. I was looking for a way to enumerate all objects currently created during a session using this forEach but have yet to succeed.

Let me elaborate.

I have a page that loads a bunch of javascript code, basically a jsp that has a bunch of script declarations.

type=”text/javascript” src=”my_scripts/audioPlayer.js”

type=”text/javascript” src=”my_scripts/videoPlayer.js”

When i use Firebug and look at the scripts i will find stuff like

audioPlayer Object

videoPlayer Object … …

Is it possible to enumerate all those Objects using forEach?

Any suggestion would be appreciated Thanks

  • Comment by: Eric
  • Posted:

@Eric – you can use the forEach to enumerate anything.

  • Comment by: -dean
  • Posted:

Dean,

Thanks for your reply. I am able to enumerate most everything, yes, except what I have mentioned above. Chances are that your code works and the problem lies between the chair and the keyboard :) Can you share some clues on how I should proceed?

  • Comment by: Eric
  • Posted:

@Eric -

forEach (audioPlayer, function(value, key) {
    alert(key + ": " + value);
});

Not all objects have properties that can be enumerated however.

  • Comment by: -dean
  • Posted:

Thanks for the reply Dean. Enumerating audioPlayer works, as expected, but the problem I have is to be able to get to audioPlayer.

I have a jsp page that includes js code and on loading said page, those script s will get executed and create objects (like audioPlayer and many more) and I am looking for a way of discovering them, i.e. enumerating them

  • Comment by: Eric
  • Posted:

This is nice, and Mozilla is always ahead. However, I have to write cross browser code. So the awful question is ‘Does that awful browser, IE, also support foreach?’

  • Comment by: Mona Everett
  • Posted:

Comment 6 indicates that this code is intended to operate on IE 5.0, but it’s based on Function.call(), which according to MSDN was first implemented in IE 5.5. Is there some alternative?

  • Comment by: Jesse Pelton
  • Posted:

Can you make a good exampe on how to use this? I can’t make it work in my project….sorry i’m just a newbie…thanks

  • Comment by: Hallie
  • Posted:

Excellent article. Thanks.

It might be helpful to show how to create a simple print function like this for newbies:

// Example print function, it can be used like this:
//    forEach(document,forEachPrint);
function forEachPrint(msg)
{
   var element = document.getElementById("forEach");
   if( element != undefined ) {
      element.innerHTML += "<br>";
      if( msg instanceof String ) {
         for(var i=0;i < msg.length;i++) {
            if( msg.charAt(i) == " " )
               element.innerHTML += "&nbsp;";
            else
               break;
            }
         }
         element.innerHTML += msg;
   }
}

Add this into your HTML document:

<div id="forEach" style="font-family:monospace;"></div>
  • Comment by: Joe
  • Posted:

Thank you for this. I think the best part is trying to understand how the code works: Javascript types are strange and this sheds some helpful light into some dark and scary places!

  • Comment by: Evan
  • Posted:

@61 You should also be able to do this

10..forEach(function($){print($);});

  • Comment by: Michael
  • Posted:

[...] this sent me on the hunt to see if it was at all possible. A furious Google search led me to a comment by Dean Edwards (who else?). He suggested throwing yourself out of the loop and wrapping the throw in a try catch [...]

[...] Re: What do you use instead of enum? On Oct 14, 5:15*am, Kenny <kentil…@gmail.com> wrote: > I wanted to do a state machine with symbolic states, but I see enum is > not part of the standard. I only have seven, do I just make seven vars > and hand enumerate? > > kt http://dean.edwards.name/weblog/2006/07/enum/ [...]

prototype has Object.keys(myobj) for this:

http://www.prototypejs.org/api/object/keys

  • Comment by: la
  • Posted:

jPaq has this implemented the way that Mozilla suggested: http://jpaq.org/documentation/Array.prototype.forEach%28%29/1.0/

  • Comment by: Verne Cane
  • Posted:

Leave A Comment

Line and paragraph breaks automatic, email address never displayed. Some HTML allowed.