ES6 -- Iterator

ES6 – Iterator

1, The concept of Iterator

  • The original data structure of JavaScript representing "Set" is mainly Array and Object. ES6 adds Map and Set. In this way, there are four kinds of data sets. Users can also combine them to define their own data structure. For example, the members of the Array are Map and the members of the Map are objects. This requires a unified interface mechanism to deal with all different data structures.
  • Iterator is such a mechanism. It is an interface that provides a unified access mechanism for various data structures. As long as the iterator interface is deployed for any data structure, the traversal operation can be completed (that is, all members of the data structure can be processed in turn).

2, Function of traverser

  • (1) Provide a unified and simple access interface for various data structures;
  • (2) Enable the members of the data structure to be arranged in a certain order;
  • (3) ES6 creates a new traversal command for... of loop, and the Iterator interface is mainly used for... of consumption (the object traversed by for must have the Iterator interface before it can be traversed)

3, Iterator traversal process

  • (1) Create a pointer object to the starting position of the current data structure. That is, the traverser object is essentially a pointer object.
  • (2) By calling the next method of the pointer object for the first time, you can point the pointer to the first member of the data structure.
  • (3) The second time the next method of the pointer object is called, the pointer points to the second member of the data structure.
  • (4) Keep calling the next method of the pointer object until it points to the end of the data structure.
    Every time the next method is called, the information of the current member of the data structure will be returned. Specifically, it is to return an object containing two attributes: value and done. The value attribute is the value of the current member, and the done attribute is a Boolean value indicating whether the traversal is over.

4, The interface implementation of self simulation traverser

1. General implementation

    function makeInterator(array){
        let startIndex=0;
        return {
            next:function(){
                return startIndex<array.length?{value:array[startIndex++],done:false}:{value:undefined,done:true}
            }
        }
    }
    let inter=makeInterator([1,2,3,4]);
    console.log(inter.next());
    console.log(inter.next());
    console.log(inter.next());
    console.log(inter.next());
    console.log(inter.next());

2. Writing method of class deployment Iterator interface (es6 deployment Iterator class, equivalent to es5 function)

  • Symbol. The iterator property corresponds to a function that returns the iterator object of the current object after execution.

    {
        class Range{
            start;
            end;
            constructor(start,end){
                this.start=start;
                this.end=end;
            }
            [Symbol.iterator](){
                return this;
            }
            next(){
                let startValue=this.start;
                if(startValue<this.end){
                    this.start++;
                    return {value:startValue,done:false};
                }
                return {value:undefined,done:true};
            }
        }
        let range=new Range(0,5);
        console.log(range.next());//{value: 0, done: false}
        console.log(range.next());//{value: 1, done: false}
        console.log(range.next());//{value: 2, done: false}
        console.log(range.next());//{value: 3, done: false}
        console.log(range.next());//{value: 4, done: false}
        console.log(range.next());//{value: undefined, done: true}
        for(let value of range){
            console.log(value);//0 1 2 3 4
        }
    }
    

3. Simulate the function class writing method of es5 to deploy an ergodic

    {
        function Range(start,stop){
            this.start=start;
            this.end=stop;
        }
        Range.prototype[Symbol.iterator]=function(){
            return this;
        }
        Range.prototype.next=function(){
            let startValue=this.start;
            if(startValue<this.end){
                this.start++;
                return {value:startValue,done:false};
            }
            return {value:undefined,done:true};
        }
        let range=new Range(0,10);
        for(let value of range){
            console.log(value);//0 1 2 3 4 5 6 7 8 9
        }
    }
  • The above code defines a makeIterator function, which is an ergodic generator function that returns an ergodic object. Executing this function on the array [1,2,3,4] will return the inter of the ergodic object (i.e. pointer object) of the array.
  • The next method of the pointer object, which is used to move the pointer. At the beginning, the pointer points to the beginning of the array. Then, every time the next method is called, the pointer points to the next member of the array. The first call, pointing to 1; The second call, pointing to 2.
  • The next method returns an object that represents the information of the current data member. This object has two attributes: value and done. The value attribute returns the member of the current position. The done attribute is a Boolean value indicating whether the traversal is over, that is, whether it is necessary to call the next method again.
  • In short, by calling the next method of the pointer object, you can traverse the data structure given in advance.
  • For the traverser object, the done: false and value: undefined attributes can be omitted

5, Default Iterator interface

1. Purpose of iterator interface

  • The purpose of Iterator interface is to provide a unified access mechanism for all data structures, that is, for... Of loop. When a for... Of loop is used to traverse a data structure, the loop will automatically look for the Iterator interface.
  • A data structure is called "iteratable" as long as the Iterator interface is deployed.
  • ES6 stipulates that the default iterator interface is deployed on the symbol of the data structure Iterator attribute, or a data structure with symbol The iterator attribute can be considered "iteratable". Symbol. The iterator attribute itself is a function, which is the default iterator generation function of the current data structure. Executing this function returns an iterator. As for the attribute name symbol Iterator, which is an expression that returns the iterator property of the symbol object. This is a predefined special value of type symbol, so it should be placed in square brackets.
  • Some data structures in ES6 have an iterator interface (such as array) natively, that is, they can be traversed by a for... Of loop without any processing. The reason is that these data structures are natively deployed with symbol Iterator attribute, and some other data structures do not (such as objects). Where symbol. Is deployed The data structure of the iterator attribute is called the deployed iterator interface. Calling this interface will return an ergodic object.

2. The data structure with native Iterator interface is as follows.

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • arguments object of function
  • Object NodeList

Example: symbol of array Iterator property

    let arr=[1,2,3,4];
    let inter=arr[Symbol.iterator]();
    console.log(inter.next());
    console.log(inter.next());
    console.log(inter.next());
    console.log(inter.next());
    console.log(inter.next());
    for(let key of arr){
        console.log(key);//1 2 3 4
    }

  • The variable arr is an array. It has a native ergodic interface and is deployed in the symbol of arr Iterator attribute. Therefore, call this property to get the ergodic object.
  • For the data structures that deploy the Iterator interface natively, you don't need to write the ergodic generation function yourself, and the for... Of loop will automatically traverse them. In addition, the Iterator interfaces of other data structures (mainly objects) need to be in symbol The Iterator attribute is deployed above, so that it can be traversed by the for... Of loop.

6, The traversal interface of the deployment object

1. Why does the object have no ergodic interface

  • The reason why an Object does not deploy the Iterator interface by default is that it is uncertain which attribute of the Object is traversed first and which attribute is traversed later, which needs to be manually specified by the developer. In essence, ergodic is a kind of linear processing. For any nonlinear data structure, deploying ergodic interface is equivalent to deploying a kind of linear transformation. However, strictly speaking, the Object deployment traverser interface is not necessary, because at this time, the Object is actually used as a Map structure. ES5 does not have a Map structure, but ES6 natively provides it.
  • If an object wants to have an Iterator interface that can be called by the for... of loop, it must be in symbol The Iterator's properties deploy the Iterator generation method (objects on the prototype chain can also have this method).

2. Deploy the traversal interface of the object

    let obj = {
        data: [ 'hello', 'world' ],
        [Symbol.iterator]() {
        const self = this;
        let index = 0;
        return {
            next() {
                if (index < self.data.length) {
                    return {value: self.data[index++], done: false};
                }
                return { value: undefined, done: true };
            }
        };
        }
    };
    let iterator=obj[Symbol.iterator]();
    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());
    for(let key of obj){
        console.log(key);//hello world
    }

  • For objects similar to arrays (with numeric key names and length attributes), a simple way to deploy the Iterator interface is symbol The Iterator method directly references the Iterator interface of the array.

    let obj={
        0:'a',
        1:'b',
        2:'c',
        3:'d',
        length:4,
        [Symbol.iterator]:Array.prototype[Symbol.iterator]
    }
    for(let value of obj){
        console.log(value);//a b c d
    }
    
  • Note that ordinary objects deploy the symbol of the array Iterator method, no effect.

    let iterable = {
        a: 'a',
        b: 'b',
        c: 'c',
        length: 3,
            [Symbol.iterator]: Array.prototype[Symbol.iterator]
    };
    for (let item of iterable) {
        console.log(item);//undefined,undefined,undefined
    }
    

7, Iterator interface of string

  • A string is an array like object that also has a native Iterator interface.

    {
        let str="Hello world!";
        let inter=str[Symbol.iterator]();
        for(let value of inter){
            console.log(value);//H e l l o   w o r l d !
        }
    }
    

8, Occasion of calling Iterator interface

  • On some occasions, the iterator interface (i.e. Symbol.iterator method) will be called by default. In addition to the for... of loop described below, there are several other occasions.
  • (1) Deconstruction assignment
    When deconstructing and assigning values to array and Set structures, symbol will be called by default Iterator method.
  • (2) Extension operator
    The extension operator (...) also calls the default Iterator interface.
  • (3)yield*
    yield * is followed by a traversable structure, which will call the traverser interface of the structure.
  • (4) Other occasions
    Since the traversal of the array will call the traversal interface, any occasion that accepts the array as a parameter actually calls the traversal interface. Here are some examples.
    for...of
    Array.from()
    Map(), Set(), WeakMap(), WeakSet() (for example, new Map([['a', 1], ['b', 2]])
    Promise.all()
    Promise.race()

Keywords: Javascript Front-end html Interview

Added by uluru75 on Wed, 23 Feb 2022 18:13:20 +0200