Basically, an iterator is an object that is able to maintain the correct iteration sequence over a collection, and provides a
next() method that effectively increments the iteration index while returning and object with two properties:
done. Managing the internal state of the iteration sequence is a manual, imperative process that can be simplified with the counterpart to iterators, namely generators.
The Array and Map objects store their default iterators (the one invoked inside for...of loops) under the
Symbol.iterator property. Generic objects do not have an iterator defined by default and thus can't immediately be used in for...of loops. Here is an example of how to use generators to assign an iterator to an object that will list all of its own enumerable and symbol properties in a for...of loop.
If you want to iterate over the object manually you can assign the iterator to a variable and do something like this:
Now that the object has an iterator defined its simple to turn it into an array of property values with the use of the spread operator.
Finally, generators provide a great way to efficiently iterate over large data sets due to their on-demand calculations. For example, suppose you had a large string that you wanted to alter before iterating over. If it was a very large string it could be difficult to store the changed data in an array due to memory constraints. Instead, you could use a generator comprehension to return an iterator for lazy execution.