Iterator

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:

  • Iterator creates an iterator using symbol. iterator that points to the start 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:

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

In the above example, we first create an array, then use symbol. iterator to create an iterator, and then call next repeatedly to access the items in the array until done is true.

Iterators are part of the protocol (the rules that use them) and are used for iteration. A key feature of this protocol is that it is sequential: iterators return one value at a time. This means that if an iterable data structure is nonlinear (such as a tree), iteration will linearize it.

Iterable data structures

Here are the iterable values:

  • Array
  • String
  • Map
  • Set
  • Dom elements (in progress)

We will use for… The of loop (see for… Of loop) iterates over the data structure.

Array

Arrays and TypedArray are both iterable.

for (let item of ["zero"."one"."two"]) {  
    console.log(item); 
} 
// output: 
// zero 
// one 
// two
Copy the code

String

Strings are iterable, but they iterate over Unicode codes, each of which may contain one or two Javascript characters.

for (const c of 'z\uD83D\uDC0A') {
    console.log(c); 
} 
// output: 
// z 
// \uD83D\uDC0A
Copy the code

Map

Maps mainly iterate through their entries, each entry encoded as a [key, value] entry, and the entries are iterated in the same order as they were added.

const map = new Map(a); map.set(0."zero"); 
map.set(1."one");  
for (let item of map) {  
    console.log(item); 
} 
// output: 
// [0, "zero"] 
// [1, "one"]
Copy the code

Note: WeakMaps are not iterative

Set

A Set iterates over its elements in the same order as it was added to

const set = new Set(a); set.add("zero"); 
set.add("one");  
for (let item of set) {
    console.log(item);
} 
// output: 
// zero 
// one
Copy the code

Note: WeakSets are not iterative

arguments

Arguments is currently used less and less in ES6, but is also traversable

function args() {
    for (let item of arguments) {
        console.log(item);
    }
} args("zero"."one"); 
// output: 
// zero 
// one
Copy the code

Ordinary objects cannot be iterated

Ordinary objects are created by object and cannot be iterated:

// TypeError 
for (let item of{{})console.log(item); 
}
Copy the code

for… Of circulation

for… Of is a new loop introduced in ES6 to replace for.. In and forEach(), and support for new iteration protocols. It can be used to iterate over regular data types, such as Array, String, Map, and Set.

Iterate over general data types

Array

const nums = ["zero"."one"."two"];
for (let num of nums) {
    console.log(num); 
} 
// TypedArray 
const typedArray1 = new Int8Array(6); 
typedArray1[0] = 10; 
typedArray1[1] = 11;
for (let item of typedArray1) {
    console.log(item);
}
Copy the code

String

const str = "zero";  
for (let item of str) {
    console.log(item);
}
Copy the code

Map

let myMap = new Map(a); myMap.set(0."zero"); 
myMap.set(1."one"); 
myMap.set(2."two");  
// Iterate over key and value
for (let [key, value] of myMap) {
    console.log(key + "=" + value);
}
for (let [key, value] of myMap.entries()) {
    console.log(key + "=" + value);
}  
// just iterate over the key
for (let key of myMap.keys()) {
    console.log(key);
}  
// Just iterate over value
for (let value of myMap.values()) {
    console.log(value);
}
Copy the code

Set

let mySet = new Set(a); mySet.add("zero"); 
mySet.add("one"); 
mySet.add("two");  
// iterate through the set
for (let item of mySet) {
    console.log(item);
}  
// Only the key value is iterated
for (let key of mySet.keys()) {
    console.log(key);
}  
// Just iterate over value
for (let value of mySet.values()) {
    console.log(value);
}  
// Iterate over key and value, both will be equal
for (let [key, value] of mySet.entries()) {
    console.log(key + "=" + value);
}
Copy the code

Iterable data structures

The of operands must be iterable, which means they cannot iterate if they are ordinary objects. If the data structure resembles the form of an Array, you can use the array.from () method to iterate over the transformation.

const arrayLink = {
    length: 2.0: "zero".1: "one"
}
// TypeError is reported
for (let item of arrayLink) {
    console.log(item);
}  
// It is running properly
for (let item of Array.from(arrayLink)) {
    console.log(item);
}
// output: 
// zero 
// one 
Copy the code

Let, const, and var for for.. of

If you use let and const, each iteration creates a new storage space, which ensures that the scope is inside the iteration.

const nums = ["zero"."one"."two"];
for (const num of nums) {
    console.log(num);
} 
/ / ReferenceError
console.log(num);
Copy the code

We can see from the above example that the last sentence will raise an exception. The scope of reason num is only inside the body of the loop. This is not the case with VAR because var is global and iteration will not create a new storage space each time.

const nums = ["zero"."one"."two"];
forv (var num of nums) {
    console.log(num);
} 
console.log(num);
// output: two
Copy the code