秒表实现js
使用 Date 对象实现基础秒表
通过 Date 对象记录开始时间和当前时间,计算差值实现秒表功能:
let startTime;
let elapsedTime = 0;
let timerInterval;
function startTimer() {
startTime = new Date() - elapsedTime;
timerInterval = setInterval(updateTimer, 10);
}
function updateTimer() {
const currentTime = new Date();
elapsedTime = currentTime - startTime;
displayTime(elapsedTime);
}
function displayTime(time) {
const formattedTime = new Date(time).toISOString().substr(11, 8);
document.getElementById('display').textContent = formattedTime;
}
function pauseTimer() {
clearInterval(timerInterval);
}
function resetTimer() {
clearInterval(timerInterval);
elapsedTime = 0;
document.getElementById('display').textContent = '00:00:00';
}
使用 performance.now() 实现高精度秒表
对于需要更高精度的场景(如游戏、性能测试),推荐使用 performance.now():
let startTimestamp;
let running = false;
let accumulatedTime = 0;
function start() {
if (!running) {
startTimestamp = performance.now();
running = true;
requestAnimationFrame(update);
}
}
function update() {
if (running) {
const currentTime = performance.now();
const elapsed = (currentTime - startTimestamp) + accumulatedTime;
render(elapsed);
requestAnimationFrame(update);
}
}
function pause() {
if (running) {
accumulatedTime += performance.now() - startTimestamp;
running = false;
}
}
function reset() {
accumulatedTime = 0;
running = false;
render(0);
}
function render(time) {
const seconds = Math.floor(time / 1000) % 60;
const minutes = Math.floor(time / 60000) % 60;
const hours = Math.floor(time / 3600000);
document.getElementById('display').textContent =
`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
}
使用 Web Worker 实现后台计时
避免主线程阻塞的解决方案:
// main.js
const timerWorker = new Worker('timer-worker.js');
timerWorker.onmessage = function(e) {
document.getElementById('display').textContent = e.data;
};
document.getElementById('start').addEventListener('click', () => {
timerWorker.postMessage('start');
});
// timer-worker.js
let startTime;
let interval;
self.onmessage = function(e) {
if (e.data === 'start') {
startTime = Date.now();
interval = setInterval(() => {
const elapsed = Date.now() - startTime;
const timeStr = new Date(elapsed).toISOString().substr(11, 8);
self.postMessage(timeStr);
}, 100);
}
};
完整组件化实现示例
封装为可复用的 ES6 类:
class Stopwatch {
constructor(displayElement) {
this.display = displayElement;
this.isRunning = false;
this.startTime = 0;
this.elapsedTime = 0;
}
start() {
if (!this.isRunning) {
this.startTime = Date.now() - this.elapsedTime;
this.isRunning = true;
this.tick();
}
}
tick() {
if (this.isRunning) {
this.elapsedTime = Date.now() - this.startTime;
this.display.textContent = this.formatTime(this.elapsedTime);
requestAnimationFrame(() => this.tick());
}
}
pause() {
this.isRunning = false;
}
reset() {
this.isRunning = false;
this.elapsedTime = 0;
this.display.textContent = this.formatTime(0);
}
formatTime(milliseconds) {
const date = new Date(milliseconds);
return date.toISOString().substr(11, 8);
}
}
// 使用示例
const display = document.getElementById('display');
const myStopwatch = new Stopwatch(display);
注意事项
- 浏览器兼容性:
performance.now()在现代浏览器中支持良好,但在旧版IE中需要polyfill - 内存泄漏:清除不再使用的interval或animation frame
- 移动端优化:考虑使用
requestAnimationFrame而非setInterval以获得更好的电池效率 - 暂停精度:累计暂停时间时要注意时间补偿逻辑







