Introduction to the

Iterator is a new traversal mechanism introduced in ES6. Iterators have two core concepts:

  • Iterators are a unified interface that makes various data structures easily accessible through a Symbol. Iterator method.
  • Iterators are Pointers used to iterate over data structure elements (such as cursors in a database).

The iterative process

The process of iteration is as follows:

  • throughSymbol.iteratorCreates an iterator that points to the starting position of the current data structure
  • The next method will return the object at the current position, which contains two attributes: value is the value of the current attribute, and done is used to determine whether the traversal is over
  • The traversal ends when done is true

Here is a simple example:

//Array
const items = ["zero", "one", "two"]; 
const it = items[Symbol.iterator](); 
it.next(); 
>{value: "zero", done: false} 
it.next();
>{value: "one", done: false} 
it.next(); 
>{value: "two", done: false} 
it.next(); 
>{value: undefined, done: true}
Copy the code
//Map
const map = new Map(); 
map.set("a",1);
map.set("b",2);
map.set("c",3);
const it = map[Symbol.iterator](); 
it.next(); 
>{value: Array(2), done: false}
it.next();
>{value: Array(2), done: false}
it.next(); 
>{value: Array(2), done: false}
it.next(); 
>{value: undefined, done: true}
Copy the code

Iterable data structures

Here are the iterable values:

  • Array

  • String

  • Map

  • Set

  • NodeList (document. GetElementsByName (” XXX “), the return value)

    1. NodeList is an array-like object that holds an ordered set of nodes
    2. The value of NodeList can be accessed through square brackets, and it has the item() method and the length attribute.
    3. It’s not an Array column, there’s no Array object method.
  • arguments

  • Generator

What is the for… Of circulation

ES6 uses C++, Java, C#, and Python to introduce for… The of loop, as a unified way to traverse all data structures.

A data structure that deploys the Symbol. Iterator attribute is considered to have an iterator interface. The of loop iterates through its members. That is to say, for… Inside the of loop is the symbol. iterator method of the data structure.

for… The of statement creates a loop to iterate over an iterable object. For… introduced in ES6. Of cycle instead of for… In and forEach(), and support the new iteration protocol. for… Of allows you to iterate through Arrays, Strings, Maps, Sets,DOM NodeList objects, Arguments, and Generator objects.

Syntax: for (variable of iterable) {statement}

Eg: Several common traversals

1: Maps

A Map object holds key-value pairs. Objects and raw values can be used as keys or values. Map objects iterate over elements based on how they are inserted. In other words, for… The of loop returns an array of key-values for each iteration.

//map-example.js 
const iterable = new Map([['one', 1], ['two', 2]]);   
for (const [key, value] of iterable) { 
    console.log(`Key: ${key} and Value: ${value}`); 
}   
// Output: 
// Key: one and Value: 1 
// Key: two and Value: 2
Copy the code

2: Set

Set objects allow you to store unique values of any type, which can be primitive values or objects. A Set object is just a collection of values. Set elements are iterated over based on their insertion order. A value in a Set can occur only once. If you create a Set with multiple identical elements, it is still considered a single element.

// set-example.js 
const iterable = new Set([1, 1, 2, 2, 1]);   
for (const value of iterable) { 
    console.log(value); 
} 
// Output: 
// 1 
// 2
Copy the code

Even though our Set has multiple ones and twos, it outputs only ones and twos.

3: Arguments Object

Think of a parameter object as an array-like object corresponding to the parameters passed to the function. Here’s a use case:

// arguments-example.js 
function args() { 
    for (const arg of arguments) { 
        console.log(arg); 
    } 
}   

args('a', 'b', 'c'); 
// Output: 
// a 
// b 
// c
Copy the code

You might be thinking, what’s going on? ! As mentioned earlier, arguments receive any arguments passed to the args() function when a function is called. So, if we pass 20 arguments to the args() function, we will print out 20 arguments

4: Generators

A generator is a function that can exit a function and re-enter it later.

// generator-example.js 
function* generator(){ 
    yield 1; yield 2; yield 3; 
};   
for (const g of generator()) { 
    console.log(g); 
}   

// Output: 
// 1 
// 2 
// 3
Copy the code

Function * defines a Generator function that returns a Generator object.

5: array-like objects that are not Iterators

Not all array-like objects have an Iterator interface, and a handy solution is to use the array. from method to convert them to an Array.

let arrayLike = { length: 2, 0: 'a', 1: 'b' }; For (let x of arrayLike) {console.log(x); } for (let x of array. from(arrayLike)) {console.log(x); }Copy the code

6: the for… Of traverses the object

For ordinary objects, for… The of structure cannot be used directly and an error will be reported. Use for… In traverses the key name of an object.

let obj = {
    a: 1,
    b: 2,
    c: 3
}

for (let e in obj) {
    console.log(e);  // 'a'  'b'  'c'
}
Copy the code

The reason why objects do not lay out iterator interfaces is that the members of arrays, maps and other structures are ordered, that is, linear structures. However, there is no definite order for each member of objects, so it is uncertain which member is iterated first and which one is iterated next. So, to deploy the Iterator interface to an object is to perform a linear transformation on that object. If you need to do this, you will need to manually deploy the Iterator interface to your objects as follows:

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 }; } else { return { value: undefined, done: true }; }}}; }};Copy the code

Alternatively, use the object. keys method to generate an array of the Object’s key names, and then use for… Of iterates through the array.

for(let key of Object.keys(obj)) {
    console.log(key + ': ' + obj[key]);
}
Copy the code

The For… Of vs For… in

for… The of loop is only suitable for iteration. Ordinary objects are not iterable.

for… The IN loop iterates through all the enumerable properties of the object.

//for-in-example.js 
Array.prototype.newArr = () => {}; 
Array.prototype.anotherNewArr = () => {}; 
const array = ['foo', 'bar', 'baz'];   
for (const value in array) { 
    console.log(value); 
} 
// Outcome: 
// 0 
// 1 
// 2 
// newArr 
// anotherNewArr
Copy the code

for… In not only enumerates the array declaration above, it also looks for inherited non-enumeration properties from the constructor’s prototype, in this case newArr and anotherNewArr are also printed out.

What is a Generator function

The Generator function is a concrete implementation of the Iterator interface. The most important feature of the Generator is that it can control the execution of functions.

function *foo(x) { 
    let y = 2 * (yield (x + 1)) 
    let z = yield (y / 3) 
    return (x + y + z) 
} 
let it = foo(5) 
console.log(it.next()) // => {value: 6, done: false} 
console.log(it.next(12)) // => {value: 8, done: false} 
console.log(it.next(13)) // => {value: 42, done: true}
Copy the code

The above example is a Generator function. Let’s examine its execution:

  • First when the Generator function is called it returns an iterator
  • When next is executed for the first time, the pass is ignored and the function pauses at yield (x + 1), so 5 + 1 = 6 is returned
  • When next is executed the second time, the argument passed is equal to the return value of the previous yield, which always returns undefined if you pass no arguments. Let y = 2 * 12, so the second yield is equal to 2 * 12/3 = 8
  • When next is executed the third time, the passed arguments are passed to Z, so z = 13, x = 5, and y = 24 add up to 42

Generator vs async

Generator appears in ES2015. Async appears in ES2017. Async is a syntactic sugar for Generator.

2. Different execution modes. Generator execution requires the use of an executor (next(), etc.); Async functions come with an executor, which is the same as the execution of ordinary functions.

3. The syntax and semantics of async are more clear. Async means async and await means waiting. The semantics of (*) and yield for Generator functions are less straightforward;

4. Yield can only be followed by Thunk or Promise objects in a Generator. In async functions, await can be followed by a promise object or a value of primitive type (automatically converted to an immediate resovle promise object);

5. The return value is different. Generator returns a traverser, which is more troublesome than Async returns a Promise.

PS:

Break exits the current loop (if there are multiple for loops)

Return exits the entire loop. Using return directly exits the function (if there are multiple for loops).

You cannot use a return in a for, otherwise you will get an error (unless the loop is inside a function)

In Javascript, once a function is executed, it runs to the end or ends when it hits a return. No other code can interrupt it or pass in values from outside the function

The emergence of Generator functions makes it possible to break the complete operation of functions, and their syntactic behavior is completely different from that of traditional functions

The Generator function is an asynchronous programming solution provided by ES6. It is formally a normal function, but it has several notable characteristics:

The function keyword is separated by an asterisk “*” (recommended next to the function keyword).

Use yield expressions inside functions to define different internal states (multiple yields can be used)

A direct call to the Generator does not execute and does not return an Iterator Object.

Call the next method of the traverser object in turn to iterate over each state inside the Generator function