Let's say I want to rotate class names for my button on click. Clicked once becomes button-green
, twice - button-yellow
, thrice - button-red
. And then it repeats, so fourth click makes it button-green
again.
I know other techniques how to do it, I'm not asking for implementation advice. I made up this example to understand something about generators in JavaScript.
Here's my code with generator:
function* rotator(items) {
while (true) {
for (const item of items) {
yield item;
}
}
}
const classRotator = rotator([
'button-green',
'button-yellow',
'button-red',
]);
document.getElementById('my-button').addEventListener('click', event => {
event.currentTarget.classList.add(classRotator.next().value);
});
It works fine, except it never gets rid of the previous class. The most convenient way would be to read the current state before getting the next one:
// .current is not a thing:
event.currentTarget.classList.remove(classRotator.current);
Of course I can keep this value on my own and use it. Likewise, I can clear all classes I use in the rotator()
myself. I can even make my generator function yield
both previous and current value:
function* rotator(items) {
let previous;
while (true) {
for (const item of items) {
yield {
item,
previous
};
previous = item;
}
}
}
And then use it like this:
document.getElementById('my-button').addEventListener('click', event => {
const {item: className, previous: previousClassName} = classRotator.next().value;
event.currentTarget.classList.remove(previousClassName);
event.currentTarget.classList.add(className);
});
But that's not the point - for educational purpose I'm asking this question:
Can I read the current value of generator function in JavaScript? If not, is it to avoid using memory when it's not needed (this value can potentially be very big)?
JavaScript "native" APIs generally are willing to create new objects with wild abandon. Conserving memory is generally not, by any appearances, a fundamental goal of the language committee.
It would be quite simple to create a general facility to wrap the result of invoking a generator in an object that delegates the .next()
method to the actual result object, but also saves each returned value as a .current()
value (or whatever works for your application). Having a .current()
is useful, for such purposes as a lexical analyzer for a programming language. The basic generator API, however, does not make provisions for that.