6日目のゴールと今日のテーマ
6日目のテーマは、
「同じ“追加・一覧表示・全消去”なのに、中身の設計レベルを一段上げること」です。
機能の表向きは変わりません。
追加
一覧表示
全消去
でも今日は、コードの中身をこう育てます。
- タスクに「ID」を持たせて、“ひとつひとつを区別できる”状態にする
- 配列への「動的追加」が、ID や他の情報も含めて扱えることを体感する
- 再描画が「どんな情報を持っていても、冷静に画面を組み立てる“土台”」になっていると理解する
まだ「1件削除」などの機能は付けません。
でも、「ID を持つタスク配列」を作ることで、明日からの拡張に耐えられる ToDo に進化させます。
いまの ToDo を「ID なしの世界」として振り返る
現在のタスクの形
5日目まで、タスクはこんな形でした。
let todos = [
{ text: "買い物に行く" },
{ text: "勉強する" }
];
JavaScripttext だけを持ったシンプルなオブジェクト。
これでも「追加・一覧表示・全消去」は問題なくできます。
でも、いざ「このタスクだけ削除したい」「このタスクを完了にしたい」となったときに、
「どのタスクを指しているのか」を判定しにくくなります。
同じ文字列のタスクが複数あったら?
真ん中の「勉強する」だけ消したいときは?
こういうときに必要になるのが ID です。
タスクに ID を持たせる理由とイメージ
なぜ ID が必要になるのか
例えばタスクがこうだったとします。
[
{ text: "買い物に行く" },
{ text: "勉強する" },
{ text: "買い物に行く" }
]
JavaScript「上の“買い物に行く”だけ消したい」と思ったとき、text だけでは区別がつきません。
そこで、こういう形にします。
[
{ id: 1, text: "買い物に行く" },
{ id: 2, text: "勉強する" },
{ id: 3, text: "買い物に行く" }
]
JavaScriptこれなら、
- id が 1 のタスクだけ
- id が 2 のタスクだけ
というように、「どれを触るか」をハッキリ指定できます。
6日目では、まだ「ID を使った削除」はやりません。
でも 「タスクが ID を持っている状態」 を作ることが、明日からの一歩の準備になります。
ID 付きタスクを作るための「次の番号」を管理する
nextId という「カウンター」を用意する
タスクを追加するたびに、
自動で 1, 2, 3, … と増えていく ID がほしいです。
そこで、こういう変数を用意します。
let nextId = 1;
JavaScript新しいタスクを作るときに、
const todo = {
id: nextId,
text: text,
};
nextId++;
JavaScriptという形で、
- 今の
nextIdの値を id に使う - すぐ
nextIdを 1 増やしておく
というふうに管理します。
これで、
1回目の追加 → id: 1
2回目の追加 → id: 2
3回目の追加 → id: 3
と、自動で“かぶらない番号” が振られていきます。
ここでの深掘りポイントは、
「ID を自動採番するために、“変数をカウンターとして使う”」という発想です。
handleAdd を「ID 付きタスク対応」に書き換える
いまの handleAdd を ID 対応版に変える
元の handleAdd はこうでした。
function handleAdd() {
const text = inputEl.value.trim();
if (text === "") {
return;
}
const todo = { text: text };
todos.push(todo);
inputEl.value = "";
render();
}
JavaScriptこれを、ID 付きに変えます。
let todos = [];
let nextId = 1;
function handleAdd() {
const text = inputEl.value.trim();
if (text === "") {
return;
}
const todo = {
id: nextId,
text: text,
};
nextId++;
todos.push(todo);
inputEl.value = "";
render();
}
JavaScriptやっていることはこうです。
入力欄から文字列を取る。
空なら弾く。{ id: nextId, text } というタスクオブジェクトを作る。nextId を 1 増やしておく(次の準備)。
配列に push。
入力欄を空にして、render で再描画。
大事なのは、「ID の付与も“追加の一部”として自然に組み込まれている」ことです。
余計なことをしているように見えて、
実はこの ID が、これからの機能追加の“生命線”になります。
再描画は「ID を持っていても冷静」なままにする
createTodoElement で ID を「見えるように」してみる
ID を付けたので、表示上でも少しだけ「ID が存在する」ことを感じてみましょう。
今はこうでした。
function createTodoElement(todo) {
const itemEl = document.createElement("div");
itemEl.textContent = todo.text;
return itemEl;
}
JavaScriptこれを、ID も表示する形にしてみます。
function createTodoElement(todo) {
const itemEl = document.createElement("div");
itemEl.textContent = `#${todo.id}: ${todo.text}`;
return itemEl;
}
JavaScript例えば、3つ追加すると画面にはこんな感じで出ます。
#1: 買い物に行く#2: 勉強する#3: 散歩する
これで、
配列の中
ブラウザの画面
の両方で、「タスクにはIDがある」という感覚が持てます。
ここでの重要ポイントは、
「再描画の全体の流れは一切変えていない」 ことです。
render 自体は前と同じです。
function render() {
listEl.textContent = "";
todos.forEach((todo) => {
const itemEl = createTodoElement(todo);
listEl.appendChild(itemEl);
});
}
JavaScript配列の中身に ID が増えても、
render は「配列 → 画面」の変換役として、そのまま機能します。
全消去と nextId の扱いをどうするか考えてみる
全消去は「配列だけ」消すのか、「IDカウンター」もリセットするのか
handleClear は今こうなっています。
function handleClear() {
todos = [];
render();
}
JavaScriptここで考えたいのが、「nextId をどうするか」です。
選択肢は2つあります。
- nextId はそのまま(ID は増え続ける)
- nextId も 1 に戻す
どちらも間違いではありません。
それぞれの意味を考えてみます。
パターン1: nextId はそのまま
function handleClear() {
todos = [];
render();
}
JavaScriptこの場合、「過去に使ったIDは再利用しない」というポリシーになります。
1〜5まで使って全消去 → 次に追加したタスクは id: 6。
このほうが、「IDは一度使ったら二度と使わない」という意味で 一意性が強い です。
現実のアプリでも、このパターンはよく使われます。
パターン2: nextId もリセット
function handleClear() {
todos = [];
nextId = 1;
render();
}
JavaScriptこの場合、「画面をリセットしたらIDもリセットされる」動きになります。
「全部消したし、IDもリセットで気持ちよくゼロから」という感覚に近いです。
どちらを選ぶかは設計の好みですが、
6日目では「IDは使い捨てでかまわない」として パターン1(残す) で行くのをおすすめします。
大事なのは、「何となく」ではなく
「自分なりの理由を持って選択する」 ことです。
6日目の全体コードのイメージ
ID を追加したうえでの全体像を、ざっくりまとめます。
const inputEl = document.getElementById("todo-input");
const addButton = document.getElementById("add-button");
const clearButton = document.getElementById("clear-button");
const listEl = document.getElementById("todo-list");
let todos = [];
let nextId = 1;
function createTodoElement(todo) {
const itemEl = document.createElement("div");
itemEl.textContent = `#${todo.id}: ${todo.text}`;
return itemEl;
}
function render() {
listEl.textContent = "";
todos.forEach((todo) => {
const itemEl = createTodoElement(todo);
listEl.appendChild(itemEl);
});
}
function handleAdd() {
const text = inputEl.value.trim();
if (text === "") {
return;
}
const todo = {
id: nextId,
text: text,
};
nextId++;
todos.push(todo);
inputEl.value = "";
render();
}
function handleClear() {
todos = [];
// nextId はリセットしない設計にしてみる
render();
}
function handleKeyDown(event) {
if (event.key === "Enter") {
handleAdd();
}
}
function setup() {
addButton.addEventListener("click", handleAdd);
clearButton.addEventListener("click", handleClear);
inputEl.addEventListener("keydown", handleKeyDown);
render();
}
setup();
JavaScript今日のポイントは、
配列 → 「ID付きタスクの配列」になった
動的追加 → 「IDも含めたタスクオブジェクト」を push するようになった
再描画 → 「IDが増えてもブレない設計」のまま動いている
という3つの一貫性です。
6日目のまとめと、7日目へのつなぎ
今日やったことを言葉で整理します。
タスクに id を持たせて、「同じ text でも別のタスクとして区別できる」状態にした。nextId というカウンター変数を使って、「追加のたびに自動で一意なIDを割り当てる」仕組みを作った。handleAdd の中で、「入力値 → タスクオブジェクト → 配列に追加 → 再描画」という流れを、ID込みで組み立てた。createTodoElement を少し変えて ID を表示し、「配列の中のIDと画面の見た目がつながっている」感覚を持てた。
全消去時に nextId をどうするかを考えることで、「コード上の選択に理由を持つ」という設計の視点に触れた。
7日目は、ここまで作ってきた ToDo アプリの設計を、
「自分の言葉で説明できる」レベルに整理する日 になります。
配列で何を持っているのか。
動的追加は何をどう変えているのか。
再描画は何を前提にして動いているのか。
ID を持たせたことで何ができるようになったのか。
これらを説明できるようになれば、
もう「簡単 ToDo アプリ 初級編」は、きちんと卒業です。
最後にひとつだけ。
今日の中で、「あ、これアプリっぽくなってきたな」と感じたのはどこでしたか?#1: 買い物に行く のように ID がついて並んだ瞬間か、
「ID をどう扱うか」を自分で選べたところか。
その「アプリっぽさ」を感じた場所が、
あなたと“実践的なコード設計”をつなぐポイントです。
その感覚を持ったまま、7日目の総仕上げに進んでいきましょう。

