Frage

I'm trying to figure out how to add an itertor to a javascript class such that the class could be used in a for...in loop. Following the instructions from Mozilla doesn't produce the results they claim it will. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators Jsfiddle of given example: http://jsfiddle.net/KQayW/

function Range(low, high){
  this.low = low;
  this.high = high;
  this.current = low;
  this.next = function() {
    if (this.current > this.range.high)
      throw StopIteration;
    else
      return this.current++;
  }
}
function RangeIterator(range){
  this.range = range;
  this.current = this.range.low;
}
RangeIterator.prototype.next = function(){
  if (this.current > this.range.high)
    throw StopIteration;
  else
    return this.current++;
};
Range.prototype.__iterator__ = function(){
  return new RangeIterator(this);
};
var range = new Range(3, 5);
for (var i in range)
  document.getElementById("test").innerHTML = i+"</br>"; // prints 3, then 4, then 5 in sequence

It doesn't print out the numbers in the range, it prints out "__iterator__"!

Does anyone know how to get this to work?

War es hilfreich?

Lösung 3

The Mozilla document state that the Iterators feature was introduced in JavaScript 1.7. Although Chrome supports some features from 1.7, it isn't fully supported so this does not work. If you test your code in the latest Firefox version though you will see it works.

Although you probably want to append the range value rather than replacing the entire div.

http://jsfiddle.net/KQayW/2/

function Range(low, high){
  this.low = low;
  this.high = high;
  this.current = low;
  this.next = function() {
  if (this.current > this.range.high)
    throw StopIteration;
  else
    return this.current++;
  }
}
function RangeIterator(range){
  this.range = range;
  this.current = this.range.low;
}
RangeIterator.prototype.next = function(){
  if (this.current > this.range.high)
    throw StopIteration;
  else
    return this.current++;
};
Range.prototype.__iterator__ = function(){
  return new RangeIterator(this);
};
var range = new Range(3, 5);
for (var i in range)
  document.getElementById("test").innerHTML += i+"</br>"; // prints 3, then 4, then 5 in sequence

Andere Tipps

With ES2015 its simple:

function Range(start, end) {
    var ret = {};
    ret[Symbol.iterator] = function *() {
        while (start < end) 
            yield start++;
    }
    return ret;
}

Though you have to use:

for (var x of Range(1, 10))

With ES2015 it can be even more simple

const Range = (start, end) => ({
  *[Symbol.iterator]() {
    while (start < end) 
        yield start++;
  }
})

for (var x of Range(1, 10)) {
  console.log(x)
}

Or you can do it without the generator syntax. This may help if you are trying to understand how iterators work.

function range(start, end) {
    return {
        [Symbol.iterator]() {
            return this;
        },
        next() {
            return start <= end ? {value: start++} : {done: true};
        }
    };
}

console.log(...range(1, 10));

The range() function returns an 'iterable object'. The iterable object is iterable because it has a function [Symbol.iterator]() that returns an 'iterator object'. The iterator object is an iterator because it has a next() function.

In this case the iterable and the iterator are the same object, which simplifies it.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top