A generator is a normal function, but instead of returning a single value, it returns multiple values one by one. Calling a generator function doesn't execute its body immediately, but rather returns a new instance of the generator object (that is, an object that implements both, iterable and iterator protocols).
Every generator object holds a new execution context of the generator function. When we execute the next() method of the generator object, it executes the generator function's body until the yield keyword is encountered. It returns the yielded value and pauses the function. When the next() method is called again, it resumes the execution and then returns the next yielded value. The done property is true when the generator function doesn't yield any value.
A generator function is written using the function* expression. Here is an...