Long story short JavaScript understanding iteration

Many people say that loop, sometimes you forget the iteration. Iteration is to execute a program repeatedly in order, and generally there will be clear termination conditions. It's not the same thing as loop. Loop is the basis of iteration.
Iteration has two conditions

  • You need to know how to use the data structure before iterating.
  • Traversal order is not inherent in data structures.
let collection = ['1', '2', '3']; 
collection.forEach((item) => console.log(item)); 
// 1 
// 2 
// 3 

This looks familiar. Arrow functions commonly used in Java programs.

Iterator mode

Also known as "iteratable object", it implements the formal iteratable interface and can be consumed through the Iterator iterator
Iteratable objects can be understood as objects of array or collection type. They contain a finite and unambiguous traversal order of elements

// The elements of an array are finite
// An incremental index can access each element in order
let arr = [3, 1, 4]; 
// The elements of a set are finite
// Each element can be accessed in the insertion order
let set = new Set().add(3).add(1).add(4);

Iteratable objects are not necessarily collection objects, or other data structures that only have array like behavior. For example, count cycle
. Both counting loops and collections have iteratable object behavior.
Iterators are one-time objects created on demand. Each iterator is associated with an iteratable object, and the iterator exposes the API of its associated iteratable object. The iterator does not need to know the structure of the iteratable object associated with it, but only how to obtain continuous values.

Iterative protocol

To implement the iteratable interface, you need to have the ability to support iterative self identification and the ability to create Iterator interface objects. In practical implementation, it means that a default Iterator must be exposed, and the default Iterator uses symbol The Iterator property is used as the key. The default Iterator must reference an Iterator factory function, and call this factory function to get a new Iterator.
Built in Iterable interface:

  • character string
  • array
  • mapping
  • aggregate
  • arguments object
  • DOM collection types such as NodeList
    Check for default iterator properties
let num = 1; 
let obj = {}; 
// Both types do not implement iterator factory functions
console.log(num[Symbol.iterator]); // undefined 
console.log(obj[Symbol.iterator]); // undefined
let str = 'abc'; 
let arr = ['a', 'b', 'c']; 
let map = new Map().set('a', 1).set('b', 2).set('c', 3); 
let set = new Set().add('a').add('b').add('c'); 
let els = document.querySelectorAll('div'); 
// These types all implement iterator factory functions
console.log(str[Symbol.iterator]); // f values() { [native code] } 
console.log(arr[Symbol.iterator]); // f values() { [native code] } 
console.log(map[Symbol.iterator]); // f values() { [native code] } 
console.log(set[Symbol.iterator]); // f values() { [native code] } 
console.log(els[Symbol.iterator]); // f values() { [native code] }

All types that implement an iterative protocol are automatically compatible with any language feature that receives an iterative object. Native language features that receive iteratable objects include:

  • For of loop
  • Array deconstruction
  • Extension operator
  • Array.from()
  • Create collection
  • Create mapping
  • Promise.all() receives an iteratable object consisting of terms
  • Promise.race() receives an iteratable object consisting of periods
  • yield * operator
let arr = ['1', '2', '3']; 
// For of loop
for (let el of arr) { 
 console.log(el); 
}
// foo 
// bar 
// baz
// Array deconstruction
let [a, b, c] = arr; 
console.log(a, b, c); // 1, 2, 3 
// Extension operator
let arr2 = [...arr]; 
console.log(arr2); // [1, 2, 3 ] 
// Array.from() 
let arr3 = Array.from(arr); 
console.log(arr3); // [1, 2, 3 ] 
// Set constructor
let set = new Set(arr); 
console.log(set); // Set(3) {1, 2, 3 } 
// Map constructor
let pairs = arr.map((x, i) => [x, i]); 
console.log(pairs); // [['1', 0], ['2', 1], ['3', 2]] 
let map = new Map(pairs); 
console.log(map); // Map(3) { '1'=>0, '2'=>1, '3'=>2 }

iterator protocol

The iterative object mentioned above will generate a new iterator each time, which is used to iterate the iteratable object associated with it. The iterator API uses the next () method to traverse the data. Each successful call to next () returns an IteratorResult object containing the next value returned by the iterator. The current position of the iterator cannot be known without calling next().
The IteratorResult object contains two properties: done and value. Done: Boolean value, whether to call next() next time to get the next value. Value: the next value of the iteratable object.
matters needing attention:
Iterators prevent the garbage collector from reclaiming iteratable objects

Early termination iterator

The for of loop exits early through break, continue, return, or throw.

Generator Foundation

Generator: the ability to pause and resume code execution within a function block
An asterisk (*) before the function name indicates that it is a generator

// Generator function declaration
function* generatorFn() {}

Note: arrow functions cannot declare generators
The generator starts to be in the suspended execution state, implements the Iterator interface, and calls the next() method to resume execution

Interrupt execution through yield

The yield keyword can stop the generator and resume execution through next(). The yield keyword can only be used in conjunction with a generator function
Yizhong. Yield * is to serialize an iteratable object into a series of values that can be produced separately, which is no different from putting yield in a loop.

// Implement recursion
function* nTimes(n) { 
 if (n > 0) { 
	 console.log("n:"+n); 
 yield* nTimes(n - 1); 
	 console.log("n1:"+n); 
	 yield n - 1;
	  console.log("n2:"+n);
 } 
} 
for (const x of nTimes(3)) { 
 console.log("result:"+x); 
}
// n:3
// n:2
// n:1
// n1:1
// result:0
// n2:1
// n1:2
// result:1
// n2:2
// n1:3
// result:2
// n2:3

Looking at my log s, you can think about their execution order, and you can clearly see yield* nTimes(n - 1); Reverse the sequence through recursion, program 1,2,3, and then pass through yield n - 1; Suspending execution results in 0,1,2

Generator as default iterator

The generator object implements the iteratable interface, and the iterator is generated after the generator function and the default iterator are called. It is particularly appropriate to make the generator a default iterator.

class Foo { 
 constructor() { 
 this.values = [1, 2, 3]; 
 }
 * [Symbol.iterator]() { 
 yield* this.values; 
 } 
}

const f = new Foo(); 
for (const x of f) { 
 console.log(x); 
} 
// 1 
// 2 
// 3

Early termination generator

Both the return() and throw() methods can be used to force the generator to close.

Keywords: Javascript Front-end ECMAScript

Added by big.nerd on Mon, 20 Dec 2021 13:49:23 +0200