1日目のゴールと今日やること
中級編の 1 日目は
「タイマー & ストップウォッチの基礎ロジックを完全に理解する」
ことがテーマです。
今日扱うキーワードは次の 6 つ。
setTimeout
setInterval
時間管理ロジック
開始
停止
リセット
ミリ秒表示
多重起動防止
これらはタイマー系アプリの“心臓部”です。
ここを理解すると、カウントダウンタイマー、ストップウォッチ、ポモドーロタイマーなど、
あらゆる時間アプリが作れるようになります。
setTimeout と setInterval の違いを「体感」で理解する
setTimeout は「一回だけ遅らせて実行」
setTimeout(() => {
console.log("1秒後に1回だけ実行");
}, 1000);
JavaScript1000ms(1秒)後に 1回だけ 実行されます。
setInterval は「一定間隔で繰り返し実行」
setInterval(() => {
console.log("1秒ごとに繰り返し実行");
}, 1000);
JavaScript1000ms ごとに 何度も 実行されます。
深掘り:タイマーアプリでは setInterval が主役
ストップウォッチは
「0.01秒ごとに時間を更新する」
という動きが必要なので、
setInterval が圧倒的に使いやすいです。
ただし、
setInterval は“止めない限り永遠に動く”
というクセがあるため、
停止処理や多重起動防止が必須になります。
ストップウォッチの「時間管理ロジック」を理解する
ストップウォッチは「経過時間」を管理するアプリ
ストップウォッチの本質は、
スタートした時刻を覚えておき、
現在時刻との差を計算する
というだけです。
例として、スタートした瞬間の時刻を記録します。
let startTime = Date.now();
JavaScript1秒後にこう計算できます。
const elapsed = Date.now() - startTime;
JavaScriptこれで「何ミリ秒経ったか」がわかります。
深掘り:Date.now() は“ミリ秒精度の時計”
Date.now() は
「1970年からの経過ミリ秒」を返す関数です。
これを使うと、
- ミリ秒単位のストップウォッチ
- 精度の高いカウントダウン
- 時間差の計算
がとても簡単にできます。
ミリ秒 → 分・秒・ミリ秒に変換する
変換ロジック
例えば 12,345ms を表示したいとします。
const ms = elapsed % 1000;
const totalSeconds = Math.floor(elapsed / 1000);
const seconds = totalSeconds % 60;
const minutes = Math.floor(totalSeconds / 60);
JavaScriptこれで、
minutes → 分
seconds → 秒
ms → ミリ秒
が取れます。
表示を整える(ゼロ埋め)
function pad(num, size) {
return num.toString().padStart(size, "0");
}
JavaScript表示例:
`${pad(minutes, 2)}:${pad(seconds, 2)}.${pad(ms, 3)}`
JavaScript深掘り:ミリ秒表示は「桁数が命」
ミリ秒は 0〜999 なので、
必ず 3 桁で表示しないと見た目が崩れます。
setInterval を使ったストップウォッチの基本構造
コードの骨格
let startTime = 0;
let timerId = null;
function start() {
startTime = Date.now();
timerId = setInterval(update, 10); // 0.01秒ごと
}
function update() {
const elapsed = Date.now() - startTime;
display(elapsed);
}
function stop() {
clearInterval(timerId);
}
function reset() {
clearInterval(timerId);
display(0);
}
JavaScript深掘り:update 関数は「画面を更新するだけ」
update の役割は、
- 経過時間を計算
- 表示を更新
この 2 つだけです。
ロジックを分離することで、
コードが読みやすくなり、バグも減ります。
多重起動防止の考え方
なぜ必要なのか?
start ボタンを連打すると、
setInterval が何個も動き始めてしまいます。
すると、
- 時間が2倍速・3倍速で進む
- 停止しても止まらない
- リセットしても動き続ける
などの“タイマー暴走”が起きます。
防止ロジック
let isRunning = false;
function start() {
if (isRunning) return; // すでに動いているなら何もしない
isRunning = true;
startTime = Date.now();
timerId = setInterval(update, 10);
}
function stop() {
clearInterval(timerId);
isRunning = false;
}
JavaScript深掘り:状態管理(isRunning)がアプリを安定させる
タイマー系アプリは
「今動いているかどうか」を
必ず状態として持つ必要があります。
これを怠ると、
ほぼ確実にバグります。
1日目の完成コード(シンプル版)
let startTime = 0;
let timerId = null;
let isRunning = false;
function start() {
if (isRunning) return;
isRunning = true;
startTime = Date.now();
timerId = setInterval(update, 10);
}
function update() {
const elapsed = Date.now() - startTime;
display(elapsed);
}
function stop() {
clearInterval(timerId);
isRunning = false;
}
function reset() {
clearInterval(timerId);
isRunning = false;
display(0);
}
function display(ms) {
const milliseconds = ms % 1000;
const totalSeconds = Math.floor(ms / 1000);
const seconds = totalSeconds % 60;
const minutes = Math.floor(totalSeconds / 60);
const text =
`${String(minutes).padStart(2, "0")}:` +
`${String(seconds).padStart(2, "0")}.` +
`${String(milliseconds).padStart(3, "0")}`;
document.getElementById("time").textContent = text;
}
JavaScript今日いちばん深く理解してほしいこと
setInterval は「繰り返し実行するエンジン」
ストップウォッチは
“一定間隔で update を呼び続ける”
という仕組みで動いています。
Date.now() は「経過時間を正確に測るための時計」
setInterval のズレを補正するためにも、
Date.now() を使って「差分」で時間を計算するのが重要です。
多重起動防止は「状態管理」がすべて
isRunning を使うことで、
start の暴走を完全に防げます。
2日目へのつなぎ
2日目はここからさらに、
ラップ機能
一時停止と再開
カウントダウンタイマー
アニメーション的な表示改善
など、
“タイマーアプリとしての完成度”を上げていきます。
今日の内容をしっかり理解できたあなたなら、
もう中級タイマーアプリの基礎は完璧です。

