JavaScript basics: Iterator concept and usage

Insert picture description here

1. Origin and significance

JavascriptIndicating "set" data structure, mainly Array, Object, Map, Setfour data sets, in addition, also be combined with each other between them, for example Arraythe members Map, Mapthe members Objectand the like. Therefore Javascript, a unified interface mechanism is needed to handle all different data structures.

The iterator ( Iterator) is such a mechanism. It is an interface that can provide an access mechanism (access interface) for various data structures. Any data structure deployment Iteratorinterface can complete the traversal operation of the data deconstructor (Iterator interface is mainly for for...ofuse).

Second, the specific implementation process

IteratorThe traversal process:

  1. Create a pointer object that points to the starting position of data deconstruction.
  2. The method of the pointer object is called for the first time next(), and the pointer points to the first member of the data structure.
  3. The second call to the next()method of the pointer object , the pointer points to the second member of the data structure.
  4. Call the next()method of the pointer object until it points to the end of the data structure. (Similar to the linked list in C language)

Each time the nextmethod is called , the information of the member pointed to by the pointer in the data structure is returned. The information is an object, which contains objects valuewith donetwo attributes { value: something , done: false }. The valueattribute is the value of the current member, and the doneattribute is a boolean value indicating whether the traversal is over ( done:false: indicates that the loop is not over yet,: done:trueindicates that the loop is over).

nextExamples of simulation method return values:

The following code defines a makeIteratorfunction, it is a traverser generating function, the role is to return a traverser object. ['前端','收割','机']Executing this function on an array will return the iterator object (pointer object) of the array goodjob.

var goodjob = makeIterator(['前端','收割','机'])

function makeIterator(array){
    
    
    
    var Index = 0;//形成闭包保存指针指向位置index,通过三元表达式返回当前信息对象。
    
    return {
    
    
        next: function(){
    
    
            return Index < array.length ? {
    
    value: array[index], done: false} : 
            {
    
    value: undefined, done: true};
        }
    }
}

goodjob.next()//  {value: '前端', done: false}
goodjob.next()//  {value: '收割', done: false}
goodjob.next()//  {value: '机',  done: false}
goodjob.next()//  {value: undefined, done: false}

Since Iteratoronly the specifications of the interface is added to the data structure above, therefore, that it traverses the data structure with which it is traversed, physically separate, can not traverse the object corresponding to the write data structure, or object with the traverse Simulate the data structure.

Three, the data structure with the default Iterator interface

IteratorPurpose interface for all data structures that provides a unified access mechanism, when for...ofthe time loop through some kind of data structure, the cycle will automatically look for Iteratorthe interface.

Therefore, when a certain data structure has an Iteratorinterface, it means that the data structure is traversable ( iterable).

The default Iteratorinterface to be deployed in the data structure of the Symbol.iteratorproperty, or that has a data structure as long as the Symbol.iteratorproperty can be considered to be "traversed" ( iterable). Symbol.iteratorThe attribute itself is a function, which is the default traverser generating function of the current data structure. Executing this function will return a iterator. As for the attribute name Symbol.iterator, it is an expression that returns Symbolan object of iteratorproperty, which is a pre-defined type is Symbolof special value, it should be placed within square brackets.

const object1 = {
  [Symbol.iterator] : function () {
    return {
      next: function () {
        return {
          value: 1,
          done: true
        };
      }
    };
  }
};

Objects object1are traversable ( iterable) because they have Symbol.iteratorattributes. Executing this property will return a iterator object. The fundamental characteristic of this object is its nextmethod. Each time the nextmethod is called , an information object representing the current member will be returned, with two attributes valueand sum done.

Any Symbol.iteratordata structure with attributes deployed is called a traverser interface deployed. Calling this interface will return a traverser object. That is, it can be for...oflooped through without any processing .

Native data structure with Iterator interface:

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • NodeList object
  • The arguments object of the function

Symbol.iteratorAttributes of the array :

let arr = ['前端', '收割', '机'];
let iterator = arr[Symbol.iterator]();  //因为arr中属性Symbol.iterator返回的是一个函数,
                                        //所以在[Symbol.iterator]后面添加(),使函数执行,返回一个遍历器对象

iterator.next() // { value: '前端', done: false }
iterator.next() // { value: '收割', done: false }
iterator.next() // { value: '机', done: false }
iterator.next() // { value: undefined, done: true }

Array iterator generated by for ofcalling the iteratorinterface

const arr = ['前端', '收割', '机'];

for(let v of arr) {
  console.log(v); // 前端 收割 机
}

Map traverser generated by for ofcalling the iteratorinterface

var handsome = new Map();
es6.set("GuangHui", "1handsome");
es6.set("JiaHao", "2handsome");
es6.set("NingDong", 666);
for (var [name, value] of es6) {
  console.log(name + ": " + value);
}
// GuangHui: 1handsome
// JiaHao: 2handsome
// NingDong: 666

Set iterator generated by for ofcalling the iteratorinterface

var handsome = new Set(["GuangHui", "JiaHao", "NingDong"]);
for (var boy of handsome) {
  console.log(boy);
}
// GuangHui
// JiaHao
// NingDong

The iterator generated by for ofcalling the iteratorinterface of an array-like object

// 字符串
let str = "前端收割机";

for (let s of str) {
  console.log(s); // 前 端 收 割 机
}

// DOM NodeList对象
let paras = document.querySelectorAll("p");

for (let p of paras) {
  p.classList.add("前端收割机");
}

// arguments对象
function printArgs() {
  for (let x of arguments) {
    console.log(x);
  }
}
printArgs('前端', '收割机');
// '前端'
// '收割机'

For Iteratordata structures (mainly objects) that do not have interfaces, they need to be Symbol.iteratordeployed on the properties themselves so that they can be for...oftraversed in a loop.

Cause: Object ( Object) is no reason why the default deployment Iteratorinterfaces, because of which traverse the properties of the object first, after which traverse the property is uncertain, developers need to manually specify. Essentially, the traverser is a linear process. For any non-linear data structure, deploying the traverser interface is equivalent to deploying a linear transformation.

Here the object is added as Iteratoran example of the interface:

let object2 = {
  data: [ '前端', '收割','机'],
  [Symbol.iterator]() {
    const self = this; //将this指向赋予self
    let index = 0;     //初始遍历下标
    return {
      next() {
        if (index < self.data.length) {
          return {
            value: self.data[index++], //每次调用,遍历下标自增1
            done: false
          };
        } else {
          return { value: undefined, done: true }; //遍历结束返回该对象
        }
      }
    };
  }
};

For array-like objects (keys and values exist lengthattributes), deployed Iterator interface, there is a simple method, it is Symbol.iteratorthe method of direct reference to the array Iteratorinterface.

let object3 = {
  0: '前端',
  1: '收割',
  2: '机',
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator] //直接引用数组构造函数prototype中的 Symbol.iterator属性
};
for (let item of iterable) {
  console.log(item); // '前端', '收割', '机'
}

Note that the Symbol.iteratormethod of deploying a specific data structure for ordinary objects has no effect. For example, the Symbol.iteratormethod of deploying an array of ordinary objects .

let object4 = {
    
      //该对象不存在数值键名
  a: '前端',
  b: '收割',
  c: '机',
  length: 3,
  [Symbol.iterator]: Array.prototype[Symbol.iterator]
};
for (let item of iterable) {
    
    
  console.log(item); // undefined, undefined, undefined
}

If the Symbol.iteratormethod does not correspond to a traverser generating function (that is, it returns a traverser object), the interpretation engine will report an error.

var object5 = {};

obj[Symbol.iterator] = () => '前端收割机';  //返回的是一个字符串

[...object5]  // TypeError: [] is not a function

Fourth, the occasion to call the Iterator interface

In addition to for...ofrecycling, some scenes will be called by default Iteratorinterfaces (ie Symbol.iteratormethod)

Destructuring assignment

let set = new Set().add('前端').add('收割').add('机'); //Set通过add方法进行链式添加值

let [one,two] = set;
// x='前端'; y='收割'

let [one, ...two] = set;
// one='前端'; two=['收割','机'];

Spread operator

// 例一
var str = '前端收割机';
[...str] //  ['前','端','收','割','机']

// 例二
let arr = ['是', '靓'];
['我', ...arr, '仔']
// ['我', '是', '靓', '仔']

Extended internal operator calls the Iteratorinterface, which provides a simple mechanism, it can be deployed to any Iteratorinterface data structure, by extending the operator, into an array.

yield*

yield*What follows is a traversable structure, which will call the traverser interface of the structure.

let generator = function* () {
  yield "我";
  yield* ["是","靓","仔"];
  yield "啊";
};

var iterator = generator();

iterator.next() // { value: "我", done: false }
iterator.next() // { value: "是", done: false }
iterator.next() // { value: "靓", done: false }
iterator.next() // { value: "仔", done: false }
iterator.next() // { value: "啊", done: false }
iterator.next() // { value: undefined, done: true }

Array.from()

Array.from()Input the value to the function in the form of an array, and the Array.from()function calls the Iterator interface to convert the input array into an array

let arrayLike = {
    
    
    0: '前端', 
    1: '收割',
    2: '机',
    3: ['GuangHui','JiaHao','NingDong'],
    'length': 4
}
let arr = Array.from(arrayLike)
console.log(arr) // ['前端','收割','机',['GuangHui','JiaHao','NingDong']]

Map(), Set(), WeakMap(), WeakSet()

MapEnter key-value pairs into the constructor in the form of an array. When creating an Mapobject, the Map constructor calls the Iteratorinterface, traverses and saves the key-value pairs

var goodJob  = new Map([['前端',1],['收割机',2]]) 

Promise.all()

Promise.all()Enter the value in the form of a Promise array to the function, and the Promise.all()function calls the Iterator interface to traverse and execute the promise request.

const p = Promise.all([p1, p2, p3]);

Promise.all()Method accepts an array as a parameter p1, p2, p3it is Promisean example, if not, it will first call the Promise.resolvemethod parameters into the Promiseinstance, and then further processing. Further, Promise.all()parameters of the method may not be an array, but it must have Iteratoran interface, and each member is returned Promiseinstance.

Promise.race()

Promise.race()Enter the value in the form of a Promise array to the function, and the Promise.race()function calls the Iterator interface to traverse and execute the promise request.

const p = Promise.race([p1, p2, p3]);

Promise.race()Method accepts an array as a parameter p1, p2, p3it is Promisean example, if not, it will first call the Promise.resolvemethod parameters into the Promiseinstance, and then further processing. Further, Promise.race()parameters of the method may not be an array, but it must have Iteratoran interface, and each member is returned Promiseinstance.

Added: Generatorfunction and Iteratorrelationship interface:

The Symbol.iteratormethod of the object is equal to the traverser generating function of the object, and calling this function will return a traverser object of the object. Since the Generator function is the traverser generating function, the Generator can be assigned to the Symbol.iteratorproperties of the object, so that the object has the Iterator interface.

Five, summary

  1. The iterator ( Iterator) can provide an access mechanism (access interface) for various data structures. Any data structure deployment Iteratorinterface can complete the traversal operation of the data deconstructor (Iterator interface is mainly for for...ofuse).
  2. IteratorThe traversal process: Create a pointer object that points to the starting position of data deconstruction. The next()method of the pointer object is continuously called , and the pointer moves backward until it points to the end of the data structure. Each time the nextmethod is called , the information of the member pointed to by the pointer in the data structure is returned { value: something , done: false }.
  3. Array, Map, Set, String, TypedArray, NodeLisT objects, function argumentsobjects on native includes Iteratora data structure of the interface.
  4. Call Iteratorinterface occasions: for...ofcycle, destructuring assignment, expansion yield*operators, Array.from(), Map(), Set(), WeakMap(), WeakSet(), Promise.all(), Promise.race(), .

Guess you like

Origin blog.csdn.net/imagine_tion/article/details/113119415