Understand the Generator in ES6
in Note with 0 comment
Understand the Generator in ES6
in Note with 0 comment

I have been looking at the tutorials and documents written by others before. When it's my turn to write them, I find they are very confused. So this article should be regarded as reading notes and review, simply adding a little understanding of yourself.

What is a generator

Generator, also called generator, is the most powerful new feature in ES2015. Generators are called iterators in CLU language and C # language, and enumerators in Rudy language.

The main function of the generator is to continuously iterate or enumerate the elements in an ordered sequence that conforms to a formula or algorithm through a program.

example:

The first two terms of Fibonacci series are 0 and 1. From the third term, follow the following formula:

$$ F_n = F_{n-1} + F_{n-2} (n {\\ge} 3) $$

In general, we implement it as follows:

 const fibonacci = [0,1] const n = 10 for(let i = 2; i < n-1; ++i){ fibonacci.push(fibonacci[i-1] + fibonacci[i-2]) } console.log(fibonacci)

In this case, it is necessary to determine a quantity, such as the above n=10 , to obtain the corresponding sequence. If you want to obtain it on demand, one of the methods here is to use the generator.

 function* fibo(){ let a = 0 let b = 1 yield a yield b while(true){ let next = a + b a = b b = next yield next } } let fibonacci = fibo() for(var i = 0; i < 10; i++){ console.log(fibonacci.next().value) }

From the above code, the new places are function* yield And why while(true) Will not lead to an endless cycle

Generator functions and objects

This is similar to variable declaration and assignment

first * It is the identifier of the generator function. Only with it can the program know that it is a generator

function* fibo(){} Is to declare a fibo() generator function

Then we define that the object instantiation generator is let fibonacci = fibo() This sentence

Of course, we can also use expressions to define

 let fibonacci = function* (){}

Yield statement

The yield language is a bit similar to the return statement. The difference is that when executing, it does not exit the function body, but cuts out the running of the current function. At the same time, like return, it can take something out of the function

The Fibonacci sequence generator above cuts the operation result of each time out of the execution object through the yield statement, and then brings the value to the main thread

The yield statement can bring an object to the main thread, and then the main thread can also bring an object back to the execution object of the generator through the method of the generator object

 const inputValue = yield outputValue

The main thread passes .next(val) Method to bring inputValue to the execution object of the generator

How to eat

Three steps: building generator function, starting generator, and allowing generator content

It is similar to the example of Fibonacci series above, and will not be supplemented

Generator class syntax and content

Operation method content
generator.next(value) Get the state of the next generator switch out. The first execution is the first switch out state
generator.throw(error) Throw an error to the current generator execution object and terminate the execution
generator[@@iterator] Provide the generator with a method to implement iterative objects so that they can be for-of implement

Among them, .next(value) A status object will be returned, including the running status of the current generator and the returned value, such as

 { value : Any; done : Boolean }

The generator execution object will constantly check the status of the generator. Once the last yield statement or the first return statement is encountered, it will enter the termination status, and the done attribute will change from false to true

Because the generator object itself is an iterative object, you can use for of, for example, the Fibonacci sequence generator code above

 for(var i = 0; i < 10; i++){ console.log(fibonacci.next().value) }

It can be modified as follows

 for (let n of fibonacci()) { if (n > 10) break console.log(n) }

Type detection

Generator function detection

 function isGeneratorFunction(fn){ if (Symbol && Symbol.toStringTag){ return fn[Symbol.toStringTag] === 'GeneratorFunction' } const genFn = (function* (){}).constructor return fn instanceof genFn }

Generator Object Detection

 function isGenerator(obj){ if (Symbol && Symbol.toStringTag){ return obj[Symbol.toStringTag] === 'Generator' }else if(obj.toString){ return obj.toString() === '[object Generator]' } return false }

Generator nesting

adopt yield* The syntax implementation is as follows

 function* foo(){ yield 1 yield 2 } function bar(){ yield* foo() yield 3 yield 4 } for(const n of bar()) console.log(n)

It's been a long time···

Responses