JavaScript Generator generator
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···
This article is written by Chakhsu Lau Creation, adoption Knowledge Sharing Attribution 4.0 International License Agreement.
All articles on this website are original or translated by this website, except for the reprint/source. Please sign your name before reprinting.