Iterator pattern

An Iterator.

To be an iterable, you must implement the @iterator method, which is accessible through the symbol. iterator property (possibly on the prototype object).

So can have any Symbol. The iterator attribute to determine traverse is can.

value attribute
Symbol.itarator A function with no arguments that returns an iterable satisfying the iterator protocol (iterator)

The following syntax uses iterables

  • for… of.. cycle
  • Expand syntax (arrays, function parameters)
  • yield *
  • Structure assignment
// Yield * for example
let generator = function* () {
    yield 1;
    yield* obj; // obj is an iterable. Obj is defined for block 3
    yield 5;
};
​
var iterator = generator();
iterator.next(); // {value: 1, done: false}
iterator.next(); // {value: 'yxfan', done: false}
iterator.next(); // {value: 18, done: false}
iterator.next(); // {value: 5, done: false}
Copy the code

The following data structures have iterables built in, and their prototype objects all implement the @iterator method

  • String

  • Array

  • Map

  • Set

  • The arguments object for the function

  • NodeList (document.querySelectorAll)

  • HTMLCollection (document.getElementBy….)

  • TypedArray

    const arr = ['a'.'b'.'c']; / / 1
    const iterator = arr[Symbol.iterator](); / / 2
    iterator.next(); // { value: 'a', done: false }
    iterator.next(); // { value: 'b', done: false }
    iterator.next(); // { value: 'c', done: false }
    iterator.next(); // { value: undefined, done: true }
    Copy the code

    Iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator: iterator Of on an object, you have to implement symbol. iterator manually

    const obj = {
        name: 'yxfan'.age: 18
    };
    obj[Symbol.iterator] = function() {
        const keys = Object.keys(obj);
        let index = 0; // The old must pack
        return {
            next: function() {
              const object = {
                  value: obj[keys[index]],
                  done: index < keys.length ? false : true
              }
              index++;
              returnobject; }}}const iterator = obj[Symbol.iterator]();
    console.log(iterator.next()); // {value: "yxfan", done: false}
    console.log(iterator.next()); // {value: 18, done: false}
    console.log(iterator.next()); // {value: 18, done: true}
    for(let o of obj) {
        console.log(o); // Print yxfan 18 in turn
    }
    Copy the code

    In the example above, we manually set the Symbol. Iterator property to an obj object, which is a generator function. So we can do things like for.. of.. Array like, go for… of… Object!

    Generator

    Relationship to the Iterator interface

    The [symbol. iterator] method of any object is equal to the iterator generator function of that object. Calling the iterator function returns an iterator object.

    Generator functions are iterator generators, so assign generator functions to [symbol.iterator].

    To modify the previous example:

     const obj = {
       name: 'yxfan'.age: 18,
       * [Symbol.iterator]() {
            let index = 0;
            const keys = Object.keys(this);
            for(let k of keys) {
                yield [k, this[k]]; }}};const iterator = obj[Symbol.iterator]();
    console.log(iterator.next()); // {value: ['name', 'yxfan'], done: false}
    console.log(iterator.next()); // {value: ['age', 18], done: false}
    console.log(iterator.next()); // {value: undefined, done: true}
    for(let [key, value] of obj) {
        console.log(key, value); // name yxfan age 18
    }
    Copy the code

    With generator, instead of deploying the next method in [symbol.iterator], yield the return value for each step

    The Generator method returns an iterator whose next method runs as follows

    1. encounteryieldExpression, suspends subsequent operations and will immediately followyieldThe value of the following expression as the value of the returned objectvalue
    2. Next callnextMethod, continue until the next one is encounteredyieldexpression
    3. If you don’t meet new onesyieldExpression value, runs until the end of the function, untilreturnStatement, and willreturnThe value of the expression following the statement as the value of the returned objectvalueAttribute values
    4. If the function doesn’treturnStatement of the object returnedvalueAttribute values forundefined.

    The generator function does not execute immediately

    function * g() {
        console.log('I'm not going to do it right now.');
    }
    const iterator = g();
    setTimeout(() = > {
        console.log(iterator.next());   
    }, 2000);
    Copy the code

    If g() were a normal function, it would print log immediately, but this is a generator function that returns an iterator object. I’m trying to print iterator

Function g is executed only when next is called

conclusion

This article mainly deals with Iterator patterns, so Iterator and generator are only briefly mentioned, and can be seen in ES6 for more details

By the Way, the iterator pattern is not used much in real development, but it is important to know how it is implemented.