Home  >  Article  >  Web Front-end  >  Detailed explanation of iterators and generators in JavaScript_javascript skills

Detailed explanation of iterators and generators in JavaScript_javascript skills

WBOY
WBOYOriginal
2016-05-16 16:32:521429browse

Processing each item in a collection is a very common operation. JavaScript provides many ways to iterate over a collection, from simple for and for each loops to map(), filter() and array comprehensions. ). In JavaScript 1.7, iterators and generators bring new iteration mechanisms to the core JavaScript syntax, and also provide a mechanism to customize the behavior of for...in and for each loops.

Iterator

An iterator is an object that accesses one element in a collection sequence at a time and keeps track of the current position of the iteration in the sequence. In JavaScript, an iterator is an object that provides a next() method that returns the next element in the sequence. This method throws a StopIteration exception when all elements in the sequence have been traversed.

Once an iterator object is created, it can be called explicitly by repeatedly calling next(), or implicitly using JavaScript's for...in and for each loops.

Simple iterators for iterating over objects and arrays can be created using Iterator():

Copy code The code is as follows:

var lang = { name: 'JavaScript', birthYear: 1995 };
var it = Iterator(lang);

Once initialization is complete, the next() method can be called to access the object's key-value pairs in sequence:

Copy code The code is as follows:

var pair = it.next(); //The key-value pair is ["name", "JavaScript"]
pair = it.next(); //The key-value pair is ["birthday", 1995]
pair = it.next(); //A `StopIteration` exception is thrown

The for…in loop can be used instead of explicitly calling the next() method. The loop automatically terminates when the StopIteration exception is thrown.

Copy code The code is as follows:

var it = Iterator(lang);
for (var pair in it)
Print(pair); //Output one [key, value] key-value pair in it each time

If you only want to iterate the key value of the object, you can pass the second parameter to the Iterator() function with the value true:

Copy code The code is as follows:

var it = Iterator(lang, true);
for (var key in it)
Print(key); //Output key value each time

One benefit of using Iterator() to access objects is that custom properties added to Object.prototype will not be included in the sequence object.

Iterator() can also be used on arrays:

Copy code The code is as follows:

var langs = ['JavaScript', 'Python', 'Haskell'];
var it = Iterator(langs);
for (var pair in it)
​​​ print(pair); //Each iteration outputs [index, language] key-value pair

Just like traversing an object, passing true as the second parameter will result in the traversal being the array index:

Copy code The code is as follows:

var langs = ['JavaScript', 'Python', 'Haskell'];
var it = Iterator(langs, true);
for (var i in it)
​​​ print(i); //Output 0, then 1, then 2

Use the let keyword to assign indexes and values ​​to block variables inside the loop, and you can also use Destructuring Assignment:

Copy code The code is as follows:

var langs = ['JavaScript', 'Python', 'Haskell'];
var it = Iterators(langs);
for (let [i, lang] in it)
          print(i ': ' lang); //Output "0: JavaScript" etc.

Declare a custom iterator

Some object representing a collection of elements should be iterated over in a specified way.

1. Iterating an object representing a range should return the numbers contained in the range one by one
2. The leaf nodes of a tree can be accessed using depth-first or breadth-first
3. Iterating over an object representing the results of a database query should be returned row by row, even if the entire result set has not yet been loaded into a single array
4. An iterator acting on an infinite mathematical sequence (like the Fibonacci sequence) should return results one after another without creating an infinite-length data structure

JavaScript allows you to write custom iteration logic and apply it to an object

We create a simple Range object containing low and high values:

Copy code The code is as follows:

function Range(low, high){
This.low = low;
This.high = high;
}

Now we create a custom iterator that returns a sequence containing all the integers in the range. The iterator interface requires us to provide a next() method to return the next element in the sequence or throw a StopIteration exception.

Copy code The code is as follows:

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 ;
};

Our RangeIterator is instantiated with a range instance and maintains a current property to track the current sequence position.

Finally, in order for RangeIterator to be combined with Range, we need to add a special __iterator__ method for Range. It will be called when we try to iterate over a Range and should return a RangeIterator instance that implements the iteration logic.

Copy code The code is as follows:

Range.prototype.__iterator__ = function(){
        return new RangeIterator(this);
};

Once we have completed our custom iterator, we can iterate over a range instance:

Copy code The code is as follows:

var range = new Range(3, 5);
for (var i in range)
​​​ print(i); //Output 3, then 4, then 5

Generators: a better way to build iterators

Although custom iterators are a useful tool, careful planning is required when creating them because their internal state needs to be maintained explicitly.

The generator provides very powerful functions: it allows you to define a function that contains its own iteration algorithm, and it can automatically maintain its own state.

Generators are special functions that can serve as iterator factories. If a function contains one or more yield expressions, it is called a generator (Translator's Note: Node.js also needs to add * in front of the function name to indicate it).

Note: Only code blocks contained in