4日目のゴールと今日のテーマ
4日目のテーマは「カウンターを“1個”から“複数個”へ広げること」です。
同じページにカウンターが2つ、3つ並んでいて、それぞれが独立して動くイメージです。
今日のゴールはこうです。
複数のカウンターを、1つの設計ルールで扱える。
イベント分離を「カウンター単位」でも考えられる。
数値管理を“カウンターごと”に整理して混乱しない。
機能自体は変わりません。
+1 / −1、リセット、0未満防止。
ただし「複数カウンター対応」という一気にアプリっぽい世界に入ります。
単一カウンターを“ひな型”として振り返る
昨日までの単一カウンターの構造
まず、昨日までのシンプルな1つのカウンターを頭に思い出します。
let count = 0;
const counterEl = document.getElementById("counter");
function render() {
counterEl.textContent = count;
}
function changeCount(delta) {
const next = count + delta;
if (next < 0) {
return;
}
count = next;
render();
}
function handleReset() {
count = 0;
render();
}
JavaScriptここでのポイントは三つ。
状態(count)は1つ。
表示先(counterEl)も1つ。
ボタンもこのカウンター専用。
だからこそ、シンプルでした。
複数カウンターになると何が変わるか
例えば、こういう画面を作りたいとします。
カウンターA:+1 / −1 / リセット
カウンターB:+1 / −1 / リセット
それぞれ別々に動く。
A を増やしても B には影響しない。
このときに必要になるのは、
カウンターごとに「状態」と「要素」を分けて持つこと。
同じロジックを“ひな型”として使い回すこと。
この2つです。
カウンター1つ分を「オブジェクト」として考える
「1カウンター=状態+要素+ロジック」の塊
1つのカウンターを、1つのオブジェクトでまとめてみます。
const counterA = {
count: 0,
el: document.getElementById("counter-a"),
};
JavaScriptここでは、
count が「このカウンターの数値」。
el が「このカウンターの表示場所」。
です。
この形にしておくと、「A用」「B用」といったオブジェクトを簡単に増やせます。
const counterA = {
count: 0,
el: document.getElementById("counter-a"),
};
const counterB = {
count: 0,
el: document.getElementById("counter-b"),
};
JavaScriptここでの重要ポイントは、「状態+表示場所」をセットで持っていることです。
これが後で効いてきます。
カウンター1つ分の render を関数にする
カウンターごとに render できるように、こう書きます。
function renderCounter(counter) {
counter.el.textContent = counter.count;
}
JavaScript使うときはこうです。
renderCounter(counterA);
renderCounter(counterB);
JavaScriptここでのポイントは、
「どのカウンターを描画するか」を引数で渡している。
関数の中では「counter」という“抽象的な1個”として扱っている。
という設計です。
カウンター1つ分の「数値変更ロジック」を一般化する
changeCount を「カウンター指定版」にする
昨日までの changeCount は、1つの count だけを扱っていました。
今日は、カウンターごとに動かせるようにします。
function changeCounter(counter, delta) {
const next = counter.count + delta;
if (next < 0) {
return;
}
counter.count = next;
renderCounter(counter);
}
JavaScriptここでやっていることはこうです。
どのカウンター(counter)を操作するかを引数で受け取る。
そのカウンターの count に delta を足す。
0未満なら何もしない。
OKなら count を更新して、そのカウンターだけ render。
これで、
changeCounter(counterA, 1); // A を+1
changeCounter(counterB, -1); // B を −1
JavaScriptのように、どのカウンターにも共通ロジックで対応できます。
ここが今日の最重要ポイントです。
複数ボタンとイベント分離(カウンター別)
HTML をイメージする
例えば、HTML はこんな形をイメージします。
<div>
<div id="counter-a">0</div>
<button id="a-plus">+1</button>
<button id="a-minus">−1</button>
<button id="a-reset">リセット</button>
</div>
<div>
<div id="counter-b">0</div>
<button id="b-plus">+1</button>
<button id="b-minus">−1</button>
<button id="b-reset">リセット</button>
</div>
A 用のボタン、B 用のボタンをそれぞれ持っています。
イベント登録の考え方
2日目までと同じように、「ボタンと処理を分離」します。
const aPlusButton = document.getElementById("a-plus");
const aMinusButton = document.getElementById("a-minus");
const aResetButton = document.getElementById("a-reset");
const bPlusButton = document.getElementById("b-plus");
const bMinusButton = document.getElementById("b-minus");
const bResetButton = document.getElementById("b-reset");
JavaScriptイベント登録はこう書けます。
aPlusButton.addEventListener("click", () => {
changeCounter(counterA, 1);
});
aMinusButton.addEventListener("click", () => {
changeCounter(counterA, -1);
});
aResetButton.addEventListener("click", () => {
resetCounter(counterA);
});
bPlusButton.addEventListener("click", () => {
changeCounter(counterB, 1);
});
bMinusButton.addEventListener("click", () => {
changeCounter(counterB, -1);
});
bResetButton.addEventListener("click", () => {
resetCounter(counterB);
});
JavaScriptここでの深掘りポイントは、
「どのカウンターに対する操作か」を、イベント側で選んでいること。
実際のロジック(changeCounter / resetCounter)は“カウンター1個分の処理”として共通で使い回していること。
です。
resetCounter の実装
リセットも一般化します。
function resetCounter(counter) {
counter.count = 0;
renderCounter(counter);
}
JavaScriptこれで、
resetCounter(counterA);
resetCounter(counterB);
JavaScriptどちらにも使えます。
「1カウンターの設計」を「複数カウンター」にどう広げるか
共通部分と違う部分を見分ける
ここまで来ると、こういう構造になっています。
共通ロジック(どのカウンターにも共通)
・renderCounter(counter)
・changeCounter(counter, delta)
・resetCounter(counter)
個別の違い(A 用と B 用)
・counterA / counterB の中身(element の参照)
・どのボタンがどの counter を操作するか、というイベント登録
これが「設計としてきれいな状態」です。
「共通」と「固有」が頭の中で分かれていると、
アプリを大きくするときに迷いにくくなります。
さらに発展させるとどうなるか(イメージだけ)
例えば、カウンターが3つ、4つに増えても、
counterC, counterD を作る。
HTML に C・D の要素を足す。
イベント登録で「どのボタンがどのカウンターを触るか」を書く。
だけで済みます。
共通ロジック(renderCounter / changeCounter / resetCounter)は、
そのまま一切書き換えずに使えます。
これが「拡張に強い設計」です。
4日目のミニ課題:AとBのカウンターを完成させる
ざっくりした全体像
4日目の完成イメージは、こんなコード構造です。
const counterA = {
count: 0,
el: document.getElementById("counter-a"),
};
const counterB = {
count: 0,
el: document.getElementById("counter-b"),
};
function renderCounter(counter) {
counter.el.textContent = counter.count;
}
function changeCounter(counter, delta) {
const next = counter.count + delta;
if (next < 0) {
return;
}
counter.count = next;
renderCounter(counter);
}
function resetCounter(counter) {
counter.count = 0;
renderCounter(counter);
}
function setup() {
renderCounter(counterA);
renderCounter(counterB);
aPlusButton.addEventListener("click", () => {
changeCounter(counterA, 1);
});
aMinusButton.addEventListener("click", () => {
changeCounter(counterA, -1);
});
aResetButton.addEventListener("click", () => {
resetCounter(counterA);
});
bPlusButton.addEventListener("click", () => {
changeCounter(counterB, 1);
});
bMinusButton.addEventListener("click", () => {
changeCounter(counterB, -1);
});
bResetButton.addEventListener("click", () => {
resetCounter(counterB);
});
}
setup();
JavaScriptここまで書けたら、「複数カウンター対応」の初級編としては十分です。
4日目のまとめと、5日目へのつなぎ
今日やったことを整理します。
1つのカウンターを「状態(count)+表示要素(el)」のオブジェクトとして扱った。
renderCounter(counter) / changeCounter(counter, delta) / resetCounter(counter) という“カウンター1個分の共通ロジック”を作った。
イベント側では「どのカウンターを操作するか」だけを選び、ロジックは共通関数に任せる形にした。
共通部分と個別部分(A用 / B用)の分離を意識し、「複数カウンターに拡張しやすい設計」を体験した。
5日目以降は、ここから例えば、
カウンターごとに「名前」や「色」を持たせる。
data-属性を使って、もっと汎用的に複数カウンターを扱う。
「カウンターを追加ボタンで増やす」ような発展版を考える。
といった方向に広げていけます。
最後に一つだけ。
今日の中で、「あ、これちょっと設計として気持ちいいな」と感じた瞬間はどこでしたか?
changeCounter(counter, delta) が A にも B にも使えたときか、counterA / counterB という“1個分の状態の塊”を作ったときか。
その「気持ちよさ」が、あなたの“設計のセンス”の芯になっていきます。


