Reference: personal blog post link

The reason I’m talking about iterators is to lay the foundation for a future article on the principle of async/await applications, because async/await consists of a Generator+Promise, and the Generator depends on the Iterator.

Let’s look at what is an Iterator? What is its purpose? How to use it?

# Iterator iterators

Noun: iteration iteration/iterable iterable/iterator

You’ve probably used for loops, while loops, etc., to iterate through an Array to get its value, but what about other data structures? Or is it possible to provide a unified access mechanism? To access Object, Map, Set, etc.

It is the Iterator’s turn. The Iterator is designed to solve this problem by providing a unified interface and a unified access mechanism for different data structures. Map, Set, and Array support iterators.

As the name implies, Iterator is designed for iteration. It provides a unified interface for different sets of objects, arrays, maps, and sets. For… Of depends on the Iterator.

By the way, I understand the relationship between traversal and iteration: traversal is access to all elements of a data structure, and iteration is a form of traversal.

Var it = makeIterator(['a', 'b']); it.next() // { value: "a", done: false } it.next() // { value: "b", done: false } it.next() // { value: undefined, done: true } function makeIterator(array) { var nextIndex = 0; return { next: function() { return nextIndex < array.length ? {value: array[nextIndex++], done: false} : {value: undefined, done: true} } } }Copy the code

The makeIterator function above is an iterator generator that returns an iterator object. Executing this function on an array returns the array’s iterator object, IT.

Return value and done by calling next; The value attribute returns the member of the current position, and the done attribute is a Boolean value indicating whether the traversal is complete, that is, whether it is necessary to call the next method again. When done is true, the traversal is complete.

An Iterator is an interface method that provides a unified access mechanism for different data structures. Allows the members of a data structure to be arranged in some order and accessed individually.

# Iterator specification

In the code above, the iterator object it contains a next() method that calls the next() method and returns two properties: Boolean done and value, value of unrestricted type.

Iterator objects contain properties that we know about, so how do we make an object an iterable in everyday development? (Iterables are objects that support the iterator specification.)

To be an iterable, an object must implement the @@iterator method. This means that the object (or an object in its prototype chain) must have a property with a key of @@iterator, accessible through the constant symbol. iterator.

let myIterable = {
    a: 1,
    b: 2,
    c: 3
}
myIterable[Symbol.iterator] = function() {
  let self = this;
  let arr = Object.keys(self);
  let index = 0;
  return {
    next() {
      return index < arr.length ? {value: self[arr[index++]], done: false} : {value: undefined, done: true};
    }
  }
}

var it = myIterable[Symbol.iterator]();

it.next();

for(const i of myIterable) {
  console.log(i);
}
Copy the code

Add the Symbol. Iterator property to myIterable and add two properties to the returned next method to make it an iterable. (In fact, if there is such a need, you can consider using Map).

————Iterator Iterator contains a next() method that returns two properties: done and value; An object can be modified to be an iterator by defining its symbol. iterator property, supporting for… Of traversal.

# Iterator and the Generator

Generator, like Promise, provides an asynchronous programming solution. A Generator function is a normal function with two characteristics. First, the function keyword has an asterisk * between the function name. Second, internal functions use yield expressions to define different internal states. Let’s look at the use of Generator functions:

function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
Copy the code

As you can see from the above example, when the Generator function executes, it returns an Iterator. A yield expression in a Generator remembers the state and location of the current code run, and the sequence of calls to the code will go backwards.

An Iterator is an iterable object, and a Generator uses yield or Generator expressions to generate Iterator objects, implementing the Iterator in a convenient way, fetching data in a for loop or using next() to fetch data.

Summary: Generator can be understood as an implementation of Iterator.

# Iterator application

Generator is one of the most typical applications, there are others, such as Map, Set, Array, etc. Native iterators, support for… Of circulation.

Obejct implements the Iterator interface

Object objects do not support iterators, but we can wrap them with generators.

let obj = {a: 1, b: 2, c: 3}
function* entries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}
for (let [key, value] of entries(obj)) {
  console.log(key, '->', value);
}
Copy the code

The Iterator interface is native to Array, Map, Set, String, TypedArray, function arguments, and NodeList.

Reference:

Iterator and for… Of circulation

MDN Iterative protocol

Vernacular interpretation of iterators and generators

Python/Iterator and Generator relationships

See more blog posts:

Personal gold digging more articles link jump;

GitHub blog project links to more articles jump;