Me preguntaba si hay una mejor forma orientada a objetos de crear este temporizador. (¡sin variables globales!)
let secondsPassed = 0; let timerId; function startTimer() { clearInterval(timerId); timerId = setInterval(function() { const seconds = twoDigits((Math.floor(secondsPassed )) % 60); const minutes = twoDigits(Math.floor(secondsPassed / 60) % 60); const hours = Math.floor(secondsPassed / 60 / 60); $('#timer').text(`${hours}:${minutes}:${seconds}`); secondsPassed++; }, 1000); $(window).blur(function() { clearInterval(timerId) // stop timer when user leaves tab }); $(window).focus(function() { startTimer(); // continue timer when user comes back }); }Su implementación actual es realmente incorrecta. Cada vez que llama a startTimer , se instala startTimer como un nuevo controlador de eventos de enfoque de ventana, lo que lleva a múltiples intervalos de inicio cuando enfoca la ventana por segunda vez; creciendo exponencialmente. El controlador onfocus solo debe ejecutar la línea timerId = setInterval(…) - poner eso en una función de ayuda anidada para llamar solo eso.
Esto también hace innecesario declarar las variables globalmente.
function createTimer() { let secondsPassed = 0; let timerId; function resume() { if (timerId) return; // prevent multiple intervals running at the same time timerId = setInterval(() => { const seconds = twoDigits((Math.floor(secondsPassed )) % 60); const minutes = twoDigits(Math.floor(secondsPassed / 60) % 60); const hours = Math.floor(secondsPassed / 60 / 60); $('#timer').text(`${hours}:${minutes}:${seconds}`); secondsPassed++; }, 1000); } function pause() { clearInterval(timerId); timerId = undefined; } $(window).blur(pause); // stop timer when user leaves tab $(window).focus(resume); // continue timer when user comes back resume(); // now start the timer } Ahora, ¿cómo hacer que esté orientado a objetos? Simplemente devuelva un objeto desde createTimer . Ponga resume y pause como métodos en ese objeto. Tal vez agregue algunos métodos más para iniciar, detener, restablecer, lo que necesite. Tal vez use una propiedad en el objeto en lugar de la variable local secondsPassed . O exponga la variable local usando un getter.
Y para que sea reutilizable, por supuesto, puede hacer que createTimer acepte argumentos, desde el selector del elemento de salida, hasta el propio elemento de salida, hasta una función de devolución de llamada que se llamará con la hora actual en cada marca.
Editar: con esta respuesta, primero debe implementar la clase Timer usted mismo. El código solo muestra cómo puede nombrar los métodos del temporizador, cómo crea la instancia y llama a sus funciones. El temporizador debe (principio de "separación de preocupaciones") solo manejar el conteo y proporcionar las funcionalidades necesarias, como iniciar y detener.
Si desea tener una solución OOP para su temporizador, no debe permitir que la clase Timer conozca la ID del contenedor DOM (como sugirió uno de sus comentarios a su pregunta).
Debería leer el tema usando esto: https://appdividend.com/2019/05/22/javascript-class-example-how-to-use-class-in-javascript-tutorial/
Supongamos que ya implementó la clase. Su código anterior debería verse como el siguiente:
// Create own scope for the function, so that variable are not assigned to windows-object. (function() { let secondsPassed = 0; let timer = new Timer(); // events, if necessary timer.onTick((seconds) => { secondsPassed = seconds }); timer.onStop(() => { secondsPassed = 0; }) // Called by a button function startTimer() { timer.start(); } // Example: Display alert with current timer seconds on click function displaySecondsOfTimer() { alert(timer.getSeconds()); } $(window).blur(function() { timer.stop(); // stop timer when user leaves tab }); $(window).focus(function() { timer.start(); // continue timer when user comes back }); })();Así que creo que tiene un buen ejemplo para codificar su primera clase de temporizador en JavaScript nativo. :)