5日目のゴールと今日のテーマ
5日目のテーマは、「まだ機能は同じなのに、“配列・動的追加・再描画”の理解を一段ガッチリ固めること」です。
機能としては変わりません。
追加
一覧表示
全消去
でも今日は、こういうところを狙います。
- 「配列の中身」を意識的に観察して、頭の中のイメージと結びつける
- 動的追加の中で、何がいつ変わっているのかをはっきりさせる
- 再描画が“ただのおまけ”ではなく、“アプリの中枢”だと理解する
新しい UI を増やすというより、
コードと頭の中のイメージをぴったり重ねる日にします。
ここまでの ToDo アプリの“今のかたち”をもう一度整理する
5日目スタート時点のイメージ
だいたい、こんな形になっているはずです。
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 = [];
function createTodoElement(todo) {
const itemEl = document.createElement("div");
itemEl.textContent = 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 = { text: text };
todos.push(todo);
inputEl.value = "";
render();
}
function handleClear() {
todos = [];
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ここに「配列」「動的追加」「再描画」が全部きれいに並んでいます。
5日目では、これを“ただ暗記する”のではなく、一行一行の意味を自分の言葉で説明できるようにしていきます。
配列を「アプリの記憶」として“見える化”する
todos の中身を意識的に観察する
まず、配列 todos がどんなふうに変わっているかを、
頭の中だけじゃなく「ログ」で見てみましょう。
handleAdd に、ログを足します。
function handleAdd() {
const text = inputEl.value.trim();
if (text === "") {
return;
}
const todo = { text: text };
todos.push(todo);
console.log("追加後の todos:", todos);
inputEl.value = "";
render();
}
JavaScriptこれで、ブラウザのコンソールに
タスクを追加するたびに todos の中身が表示されます。
例えば、
1回目:「買い物に行く」を追加
→ [ { text: "買い物に行く" } ]
2回目:「勉強する」を追加
→ [ { text: "買い物に行く" }, { text: "勉強する" } ]
3回目:「散歩する」を追加
→ [ { text: "買い物に行く" }, { text: "勉強する" }, { text: "散歩する" } ]
このログを見ながら、
「画面に見えている“3行のリスト”の正体は、この配列だ」
と意識して眺めてみてください。
配列が“抽象的な概念”じゃなくて、
「コンソールに映っている“生のデータ”」として見えるようになると、一気に親しみやすくなります。
動的追加の中で「何がいつ変わるか」を分解する
handleAdd を日本語に完全分解してみる
handleAdd の中で起きていることを、あえて細かく日本語にします。
function handleAdd() {
const text = inputEl.value.trim();
if (text === "") {
return;
}
const todo = { text: text };
todos.push(todo);
inputEl.value = "";
render();
}
JavaScript順番に追うと、
- 入力欄から文字列を取る(
inputEl.value)。 - 前後の空白を削る(
trim())。 - 空文字(
"")なら追加せずに終わる。 { text: "入力された文字" }という タスク用オブジェクト を作る。todos.push(...)で配列の最後にそのオブジェクトを追加する。- 入力欄を空にする(ユーザーに「追加されたよ」と伝わる小さなサイン)。
render()を呼んで、今の配列の中身から画面を作り直す。
ここで一番大事なのは、
「画面を変えるのは render、データを変えるのは handleAdd」
という分担です。
handleAddがやっているのは「配列を変えること」renderがやっているのは「配列を元に画面を作ること」
この役割分担が、配列・動的追加・再描画をつなぐ“軸”になっています。
再描画を「アプリの中枢」として身体に落とし込む
render を“どこから呼んでも同じ意味”にしておく
render の中身をもう一度見てみます。
function render() {
listEl.textContent = "";
todos.forEach((todo) => {
const itemEl = createTodoElement(todo);
listEl.appendChild(itemEl);
});
}
JavaScriptやっているのはこの2つだけです。
listElの中身を全部消す。todosの中身を先頭から順に読み、要素を作って全部追加する。
つまり、
「今の todos を、そのまま画面に映し直す」
これしかしていません。
だからこそ、
handleAddから呼んでもhandleClearから呼んでも- 将来、何か別の場所から呼んでも
「画面を“正しい状態”に整え直す」という、同じ意味 になります。
ここで少し想像してみてください。
もし render の中で、
todosを書き換えていたり- input の中身を触ったり
- 全然別のボタンの状態まで変えていたり
したらどうでしょう。
render を呼ぶたびに別のところまで勝手に変わる。
結果、「どこで何が起きるか分からない」関数になってしまいます。
「render は view(見た目)だけを担当する」
この約束を守れているのは、かなりいい状態です。
小さな実験で「配列と再描画の関係」を体感する
実験①:手動で配列を書き換えてから render してみる
例えば、コンソールからこうしてみます。
タスクを3つくらい追加したあと、ブラウザのコンソールにこう打ってみるイメージです。
todos.pop(); // 最後のタスクを1つ配列から削除
render(); // 再描画
JavaScriptすると、
- 画面からも最後の1件が消えるはずです。
ここで感じてほしいのは、
「画面をいじらなくても、配列 → render だけで見た目が変わる」
ということです。
タスクを無理やりこう書き換えてみてもいいです。
todos = [
{ text: "手動で差し替えたタスク1" },
{ text: "手動で差し替えたタスク2" },
];
render();
JavaScriptすると、画面もその2件だけになります。
これが、
配列(状態)が「真実」。
render が「その真実を描画」。
という構造そのものです。
もう一段だけ設計を意識する:createTodoElement の意味
「1件分の見た目をカプセル化する」感覚
createTodoElement は、今はこれだけです。
function createTodoElement(todo) {
const itemEl = document.createElement("div");
itemEl.textContent = todo.text;
return itemEl;
}
JavaScriptでも、ここに例えばクラス名を付けたり、
アイコンを付けたりするのは この関数だけ 触ればOKです。
function createTodoElement(todo) {
const itemEl = document.createElement("div");
itemEl.className = "todo-item";
itemEl.textContent = "• " + todo.text;
return itemEl;
}
JavaScriptすると、
- 再描画のロジック(render)は一切変えなくていい
- 配列の構造(todos)も一切変えなくていい
- 見た目だけをこの関数でコントロールできる
という状態になります。
これが、「1件分の見た目をカプセル化する」感覚です。
配列:データのまとまり
render:データ全体 → 画面全体
createTodoElement:データ1件 → 画面1件
きれいに三層に分かれています。
5日目の「頭の中での整理」を言葉にしてみる
ここで一度、あなた自身の言葉で整理してほしいポイントがあります。
質問①:配列 todos は、あなたにとって何ですか?
単なる「リスト」でもいいし、
「アプリの記憶」でもいいし、
「ToDoリストの本体」でもいい。
自分の言葉で説明してみてください。
質問②:動的追加は、どんな順番で何をしていますか?
- 値を取る
- 空を弾く
- オブジェクトにする
- 配列に push
- 入力欄を消す
- render
この流れを、1つずつ自分の言葉で説明できると、
もう「なんとなく書いている」状態から卒業です。
質問③:render を呼んだときに“必ず起こること”と、“起こらないこと”は何ですか?
起こること:
- 画面の一覧が配列
todosの中身に合わせて描き直される
起こらないこと:
todosは書き換えられない- 入力欄の中身は変わらない
- ボタンのイベントは変わらない
この「やること / やらないこと」の境界が見えていると、
関数の設計が一段レベルアップします。
5日目のまとめと、6日目へのつなぎ
今日やったのは、新しい機能ではなく 「理解の解像度を上げること」 でした。
振り返ると、こんなことをやりました。
- コンソールログを使って、配列
todosの中身と画面の対応を“目で見て”理解した。 handleAddを細かく分解し、「どのタイミングで何が変わっているか」を言葉で追えるようにした。renderは「配列 → 画面」の変換に専念していて、“いつ呼んでも安全な関数”だと確認した。- コンソールから配列を書き換えて
render()する実験で、「画面はあくまで配列の写し」という感覚を体でつかんだ。 createTodoElementが「タスク1件分の見た目」をカプセル化していることを意識し、役割の分離を感じた。
6日目以降は、いよいよ
- 1件だけ削除する
- 完了チェックを付ける
- タスクに ID や done フラグを持たせる
といった「ToDoアプリらしい動き」に踏み込んでいきます。
ただ、そのとき土台になるのは、まさに今日整理した
「配列 → 動的追加 → 再描画」という一本の流れ
です。
最後にひとつ、あなたに聞きたい。
今日の中で、「あ、自分これもう怖くないかも」と感じたのはどこでしたか?
配列の中身をログで見た瞬間か、render を“何度呼んでもいいやつ”だと理解したところか。
その「怖くなさ」が増えた分だけ、
次に一歩踏み込む余裕が生まれています。
その余裕を持ったまま、6日目の“機能強化”に進んでいきましょう。

