title: JavaScript Iterator Class
body: <p>Do you know a JavaScript library that implements a generic Iterator class for collections (be it Arrays or some abstract Enumerable) with a full set of features, like the <a href="http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Iterators.html" rel="nofollow noreferrer">Google Common</a>  or the <a href="http://commons.apache.org/collections/api-release/org/apache/commons/collections/iterators/package-summary.html" rel="nofollow noreferrer">Apache Commons</a>?</p>
  
  <p>Edit: <code>Enumerable#each</code> is not an Iterator class. I'm looking for an Iterator, something that would let us write something like:</p>
  
  <pre><code>var iterator = new Iterator(myCollection);
  for (var element = iterator.next(); iterator.hasNext(); element = iterator.next()) {
      // iterator 
  }
  </code></pre>
  
  <p>Edit : mamoo reminded us of the Iterator implementation in <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Iterators_and_Generators" rel="nofollow noreferrer">Mozilla's Javascript 1.7</a>. So the goal now is to find an implementation of this Iterator function in Javascript 1.5 (ECMA 4).</p>
  
  <p>Edit2 : Why using an iterator when libraries (and ECMA 5) provide a <code>each</code> method? First, because <code>each</code> usually messes with <code>this</code> because the callback is <code>call</code> -ed (that's why <code>each</code> accepts a second argument in Prototype). Then, because people are much more familiar with the <code>for(;;)</code> construct than with the <code>.each(callback)</code> construct (at least, in my field). Lastly, because an iterator can iterate over plain objects (see JavaScript 1.7).</p>
  
  <p>Edit3 : I accepted npup's anwser, but here is my shot at it :</p>
  
  <pre><code>function Iterator(o, keysOnly) {
      if (!(this instanceof arguments.callee))
        return new arguments.callee(o, keysOnly);
      var index = 0, keys = [];
      if (!o || typeof o != "object") return;
      if ('splice' in o &amp;&amp; 'join' in o) {
          while(keys.length &lt; o.length) keys.push(keys.length);
      } else {
          for (p in o) if (o.hasOwnProperty(p)) keys.push(p);
      }
      this.next = function next() {
          if (index &lt; keys.length) {
              var key = keys[index++];
              return keysOnly ? key : [key, o[key]];
          } else throw { name: "StopIteration" };
      };
      this.hasNext = function hasNext() {
          return index &lt; keys.length;
      };
  }
  
  
  
  var lang = { name: 'JavaScript', birthYear: 1995 };  
  var it = Iterator(lang);
  while (it.hasNext()) {
      alert(it.next());
  }
  //alert(it.next()); // A StopIteration exception is thrown  
  
  
  var langs = ['JavaScript', 'Python', 'C++'];  
  var it = Iterator(langs);
  while (it.hasNext()) {
      alert(it.next());
  }
  //alert(it.next()); // A StopIteration exception is thrown  
  </code></pre>