Digamos que quiero rotar los nombres de clase para mi botón al hacer clic. Al hacer clic una vez, se convierte en button-green , dos veces button-yellow , tres veces button-red . Y luego se repite, por lo que el cuarto clic hace que button-green .
Conozco otras técnicas de cómo hacerlo, no estoy pidiendo consejos de implementación. Hice este ejemplo para entender algo sobre los generadores en JavaScript.
Aquí está mi código con generador:
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); });Funciona bien, excepto que nunca se deshace de la clase anterior. La forma más conveniente sería leer el estado actual antes de obtener el siguiente:
// .current is not a thing: event.currentTarget.classList.remove(classRotator.current); Por supuesto que puedo mantener este valor por mi cuenta y usarlo. Del mismo modo, puedo borrar todas las clases que uso en el rotator() yo mismo. Incluso puedo hacer que mi función de generador yield tanto el valor anterior como el actual:
function* rotator(items) { let previous; while (true) { for (const item of items) { yield { item, previous }; previous = item; } } }Y luego utilízalo así:
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); });Pero ese no es el punto, con fines educativos hago esta pregunta:
¿Puedo leer el valor actual de la función del generador en JavaScript? Si no es así, ¿es para evitar el uso de la memoria cuando no se necesita (este valor puede ser potencialmente muy grande)?
¿Puedo leer el valor actual de la función del generador en JavaScript?
No.
Pero puede implementar esto usted mismo fácilmente si lo desea.
Si no, ¿es para evitar usar la memoria cuando no se necesita?
Quizás. Se supone que un iterador no debe aferrarse al último valor que ha generado, para permitir la recolección de basura independiente y para que sea económico mantener generadores agotados o aún no terminados.
Pero creo que la razón principal por la que no hay un campo .current disponible en el diseño es que no tiene sentido desde un punto de vista teórico: ¿qué valor tendría ese campo antes de que comenzara la iteración o después de que se agote el iterador? Uno podría haber optado por undefined , pero un diseño limpio simplemente no tiene el campo en absoluto y solo devuelve valores si realmente pasa el iterador.
Las API "nativas" de JavaScript generalmente están dispuestas a crear nuevos objetos con un abandono salvaje. Por lo general, conservar la memoria no es, al parecer, un objetivo fundamental del comité lingüístico.
Sería bastante simple crear una instalación general para envolver el resultado de invocar un generador en un objeto que delega el método .next() al objeto de resultado real, pero también guarda cada valor devuelto como un valor .current() (o lo que funcione para su aplicación). Tener un .current() es útil para propósitos tales como un analizador léxico para un lenguaje de programación. La API del generador básico, sin embargo, no hace provisiones para eso.