The Key Difference Between a Function and a Generator in ES6

This is largely cribbed from an explanation of generators on FrontEndMasters by Kyle Simpson. For anyone looking to level up in Javascript, I totally recommend his stuff.

Functions

Generally speaking, a function is a “subprogram” that can be called by code external (or internal in the case of recursion) to the function. Like the program itself, a function is composed of a sequence of statements called the function body. Values can be passed to a function, and the function will return a value. (Source)

The thing to keep in mind here is that functions feature a behavior called run-to-completion, which means that one a function is executed it runs continuously (and cannot be interrupted) until the function stops executing.

Generators

Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances. Calling a generator function does not execute its body immediately; an iterator object for the function is returned instead. (Source)

The purpose of a generator is to implement a function WITHOUT the run-to-completion behavior- instead, it returns an iterator object which holds the control flow. At any point the generator can be paused, and then resumed without losing its context using the .next() method that comes on the iterator.

Redundant Note Of The Day: calling the generator function doesn’t start the function running toward the first yield. It returns the iterator. I’m writing this twice because I missed it the first time I started experimenting with these.

function* myGenerator () {
console.log(1)
yield; // <-- a 'pause' button which stops execution
console.log(2);
}
const x = myGenerator() // <- return the iterator
x.next() // <- the 'play' button to run the generator until a yield
==> 1
x.next()
==> 2

Stopping a generator is as easy as putting a return statement somewhere inside. Once it returns, it will be done. If you don’t include the return, it’ll keep returning undefined from the .next() calls should they continue to be invoked.

Easy peasy.