Demonstrate the basic syntax and use of a JavaScript generator function*. Replit demo here.
Creating a randomAnimalGeneratorFunc
First, we create a Generator function that stores a list of animals (and an onion). As the Generator is iterated, a random animal (or an onion!) is yielded and then removed from the list.
function* randomAnimalGeneratorFunc() {
let animals = [
"🧅",
"cat",
"dog",
"hamster",
"bird",
"snake",
"turtle",
"guinea pig",
"horse",
"fish",
"mouse",
"lemur",
"whale",
"crab",
];
while (animals.length) {
const i = Math.floor(Math.random() * animals.length);
yield animals[i];
animals.splice(i, 1);
}
}
Notice how code after the yield
statement is reachable and executed, which is very different from a standard function return
statement.
Assigning the Generator to variables
The randomAnimalGeneratorFunc()
function is a Generator function. Each time it is called, it returns a new Generator which we can assign to a variable.
const randomAnimalGenerator = randomAnimalGeneratorFunc();
const anotherRandomAnimalGenerator = randomAnimalGeneratorFunc();
In the example above, randomAnimalGenerator
and anotherRandomAnimalGenerator
are two distinct Generators. Removing items from the animals
list in randomAnimalGenerator
has no direct effect on the animals
list in anotherRandomAnimalGenerator
.
Note that if you have a more complex data structure with nested references to arrays or objects stored in variables declared outside of the Generator function's scope, those referenced objects will experience side-effects across Generators as expected.
An animal function
const randomAnimalGenerator = randomAnimalGeneratorFunc();
const animal = () => {
const a = randomAnimalGenerator.next();
if (!a.done) {
return a.value === "🧅" ? "🧅🧅🧅🧅 Onions!!!!" : a.value;
}
return `You're out of animals (and onions).`;
};
The animal
function will return a random animal from the animals
list in randomAnimalGenerator
. If an onion is encountered, you will be notified and may use the information in your RCA report. When you've gone through the entire animals
list, you will have to reload the app to start over because I didn't bother writing a reset function.
An onion function
const randomAnimalGenerator = randomAnimalGeneratorFunc();
const onion = () => {
let o = randomAnimalGenerator.next();
while (!o.done) {
if (o.value === "🧅") {
return "🧅🧅🧅🧅 Onions!!!!";
}
console.log(o.value);
o = randomAnimalGenerator.next();
}
return `You're out of animals (and onions).`;
};
The onion
function will return a randomized list of all the animals in the animals
list. If an onion is encountered, execution will be halted to alert you of the danger. Running the onion
function a second time will return the remaining animals in random order. You will be notified when the animals
list is empty.
Putting it all together
function* randomAnimalGeneratorFunc() {
let animals = [
"🧅",
"cat",
"dog",
"hamster",
"bird",
"snake",
"turtle",
"guinea pig",
"horse",
"fish",
"mouse",
"lemur",
"whale",
"crab",
];
while (animals.length) {
const i = Math.floor(Math.random() * animals.length);
yield animals[i];
animals.splice(i, 1);
}
}
const randomAnimalGenerator = randomAnimalGeneratorFunc();
const animal = () => {
const a = randomAnimalGenerator.next();
if (!a.done) {
return a.value === "🧅" ? "🧅🧅🧅🧅 Onions!!!!" : a.value;
}
return `You're out of animals (and onions).`;
};
const onion = () => {
let o = randomAnimalGenerator.next();
while (!o.done) {
if (o.value === "🧅") {
return "🧅🧅🧅🧅 Onions!!!!";
}
console.log(o.value);
o = randomAnimalGenerator.next();
}
return `You're out of animals (and onions).`;
};
See that I've defined randomAnimalGenerator
outside of the animal
and onion
functions to demonstrate how both functions share the same Generator and any side-effects created by animal
have an impact on onion
and vice versa.
P.S., I love onions! 🧅
Top comments (1)