A JavaScript stopwatch needs two separate ideas: a timer to refresh the display and a reliable elapsed-time calculation. For elapsed duration, calculate from timestamps such as performance.now() instead of assuming every interval callback arrives exactly on time.
const start = performance.now();
// ...later
const elapsed = performance.now() - start;
The refresh timer does not define the elapsed time; it only decides how often the screen is updated. The elapsed value should be calculated from the recorded start timestamp plus any previously accumulated duration.
performance.now() provides a high-resolution monotonic timestamp designed for measuring elapsed durations. Unlike wall-clock time, it is not intended to jump when the system clock is adjusted.
if (timerId !== null) return;
startedAt = performance.now();
timerId = setInterval(render, 50);
elapsed += performance.now() - startedAt;
clearInterval(timerId);
timerId = null;
On the next Start, keep the accumulated elapsed value and record a new startedAt.
clearInterval(timerId);
timerId = null;
elapsed = 0;
A 10 ms refresh does not make a stopwatch more accurate; it only updates the DOM more often. A moderate refresh such as 50–100 ms is enough for many educational stopwatch displays. For animation tied to screen painting, requestAnimationFrame() may be a better display loop.
Date.now() works when you need a wall-clock timestamp or when persistence across reloads matters. For measuring duration within the current page session, performance.now() is generally a better fit.
Other window examples retained from the original learning path: add to favorites and redirect.
The original related analog-clock example remains available: HTML canvas clock demo. Also see countdown timer and real-time clock.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.