JavaScript / LESSON 11 / JS11

JavaScript:DOM操作の基礎

1学習の目的

2基礎解説

やりたいこと書き方備考
1つ取得するdocument.querySelector("#id")無ければ null
全部取得するdocument.querySelectorAll(".cls")複数の要素が返る
文字を書き換えるel.textContent = "新しい文字"安全。基本はこちら
要素を作って足すcreateElement / appendChild画面に組み立てる
✅ 覚えるべき重要ポイント
  1. DOMは「HTMLをJavaScriptから触れるようにしたもの」document がページ全体の入り口になる。
  2. 取得は querySelector(1つ)と querySelectorAll(全部)。CSSと同じ書き方で、#id .class tag が使える。
  3. 文字を入れるなら textContentinnerHTML はHTMLとして解釈されるため、ユーザーの入力をそのまま入れると不正なスクリプトを埋め込まれる危険がある。
  4. 見た目は classList.add / remove / toggle で切り替える。style を直接いじるより、CSSにクラスを定義しておくほうが管理しやすい。
  5. 要素が見つからないと null が返り、そのまま操作すると TypeError で止まる。IDのつづりミスが原因のことが多い。

現場使用例:ボタンを押したら文字を変える、入力内容を画面に反映、APIで取得した一覧をカードとして並べる、エラー時に赤いクラスを付ける。

<!-- HTML側 -->
<h1 id="title">こんにちは</h1>
<ul id="list"></ul>

// JavaScript側
const title = document.querySelector("#title");
title.textContent = "変更しました";      // 文字を書き換え
title.classList.add("highlight");        // クラスを追加

// 要素を作って画面に追加する
const list = document.querySelector("#list");
const items = ["りんご", "みかん"];

for (const item of items) {
  const li = document.createElement("li");
  li.textContent = item;
  list.appendChild(li);
}

// 全部まとめて操作する
document.querySelectorAll("li").forEach(li => {
  li.classList.add("item");
});

3基本ドリル(10問)

JS11-D01 id が "title" の要素を取得し、その文字を「変更しました」に書き換えよ。 コーディング★☆☆無料
期待される結果

#title の textContent が 変更しました

ヒント

document.querySelector("#title") で取得し、.textContent に代入する。

模範解答
const title = document.querySelector("#title");
title.textContent = "変更しました";
解説

取得 → 操作がDOM操作の基本の2手。querySelector はCSSと同じセレクタが使えるので、覚えることが少なくて済む。

JS11-D02 document.querySelector("#box") で要素が見つからなかったとき、戻り値は何か。
A. undefined B. null C. 空文字 D. エラーになる
選択★☆☆無料
期待される結果

解答 == B

ヒント

「無い」を明示的に表す値。

模範解答
B
解説

null のまま .textContent を書くと TypeError で止まる。IDのつづりミスや、スクリプトがHTMLより先に読まれた場合に起きる。

JS11-D03 class が "item" の要素をすべて取得し、その件数を出力せよ。 コーディング★☆☆無料
期待される結果

出力 == 3

ヒント

document.querySelectorAll(".item") で全部取れる。件数は .length。

模範解答
const items = document.querySelectorAll(".item");
console.log(items.length);
解説

querySelector は1つ、querySelectorAll は全部。All のほうは要素が0個でも null にはならず、空のリストが返る。

JS11-D04 要素の文字を安全に書き換えるコードを完成させよ。 穴埋め★☆☆無料
コード
const el = document.querySelector("#msg");
el.____ = "こんにちは";
期待される結果

#msg の textContent が こんにちは

ヒント

文字(テキスト)の中身を表すプロパティ。HTMLとして解釈されない安全なほう。

模範解答
textContent
解説

innerHTML との使い分けが重要。ユーザーが入力した文字をそのまま innerHTML に入れると、悪意あるスクリプトが動く危険がある。

JS11-D05 要素に CSS クラスを追加する正しい書き方はどれか。
A. el.class.add("on") B. el.classList.add("on") C. el.addClass("on") D. el.class = "on"
選択★☆☆無料
期待される結果

解答 == B

ヒント

クラスの「一覧」を操作するプロパティ。

模範解答
B
解説

classList には add / remove / toggle / contains がある。className = "on" と書くと既存のクラスを全部消して置き換えるので注意。

JS11-D06 id が "box" の要素に "active" クラスを追加し、そのあと "hidden" クラスを削除せよ。 コーディング★★☆無料
期待される結果

active が付き hidden が消えている

ヒント

classList.add() と classList.remove() を続けて呼ぶ。

模範解答
const box = document.querySelector("#box");

box.classList.add("active");
box.classList.remove("hidden");
解説

見た目の切り替えはクラスで行うのが基本。色や大きさはCSS側に書いておき、JavaScriptはクラスを付け外しするだけにすると役割が分かれて管理しやすい。

JS11-D07 新しい li 要素を作って list に追加するコードを完成させよ。 穴埋め★★☆無料
コード
const list = document.querySelector("#list");
const li = document.____("li");
li.textContent = "新しい項目";
list.appendChild(li);
期待される結果

#list に li が1つ追加され textContent が 新しい項目

ヒント

「要素を作る」という意味のメソッド。document から呼ぶ。

模範解答
createElement
解説

作る → 中身を入れる → 追加するの3手が要素追加の定型。createElement しただけでは画面に出ず、appendChild で初めて表示される。

JS11-D08 ユーザーが入力した文字を画面に表示するとき、安全なのはどちらか。
A. innerHTML B. textContent C. どちらも同じ D. どちらも危険
選択★★☆無料
期待される結果

解答 == B

ヒント

HTMLとして解釈されるかどうか。

模範解答
B
解説

innerHTML は文字列をHTMLとして解釈するため、<script> などを埋め込まれる危険がある(XSS)。入力された値を表示するときは必ず textContent

JS11-D09 items = ["りんご", "みかん", "ぶどう"] から li 要素を作り、id が "list" の要素に3つ追加せよ。 コーディング★★☆無料
期待される結果

#list の子要素が3つで textContent が りんご/みかん/ぶどう

ヒント

for...of で回し、毎回 createElement → textContent → appendChild を行う。

模範解答
const list = document.querySelector("#list");
const items = ["りんご", "みかん", "ぶどう"];

for (const item of items) {
  const li = document.createElement("li");
  li.textContent = item;
  list.appendChild(li);
}
解説

データから画面を組み立てる——これがDOM操作の本質。配列の中身が変わればそのまま画面が変わるので、HTMLを手で書く必要がなくなる。

JS11-D10 class が "item" の要素すべてに "done" クラスを追加せよ(forEach を使うこと)。 コーディング★★☆無料
期待される結果

すべての .item に done が付いている

ヒント

querySelectorAll の結果は forEach で回せる。

模範解答
document.querySelectorAll(".item").forEach((el) => {
  el.classList.add("done");
});
解説

querySelectorAll の結果は forEach で回せるが、map や filter は使えない場合がある。配列として扱いたいときは [...document.querySelectorAll(…)] と展開する。

4実践シナリオ(5問)

JS11-S01 【商品リストの表示】products = [{ name: "ノートPC", price: 128000 }, { name: "マウス", price: 3200 }] から、「ノートPC:128,000円」という文字を持つ li を作り、id が "list" の要素に追加せよ。 コーディング★★☆無料
期待される結果

#list に li が2つ、textContent が ノートPC:128,000円 / マウス:3,200円

ヒント

for...of で回し、テンプレートリテラルで文字を組み立ててから textContent に入れる。

模範解答
const products = [
  { name: "ノートPC", price: 128000 },
  { name: "マウス", price: 3200 },
];

const list = document.querySelector("#list");

for (const p of products) {
  const li = document.createElement("li");
  li.textContent = `${p.name}:${p.price.toLocaleString()}円`;
  list.appendChild(li);
}
解説

JS07で学んだオブジェクトの配列が、そのまま画面の一覧になった。データと表示が分離しているので、products を差し替えるだけで表示が変わる。

JS11-S02 【条件でクラスを付ける】scores = [82, 45, 91] から li を作り、id が "list" に追加せよ。60点以上なら "pass"、未満なら "fail" クラスを付けること。文字は「82点」の形式。 コーディング★★☆無料
期待される結果

3つの li に pass/fail/pass が付いている

ヒント

createElement のあと classList.add() で条件に応じたクラスを付ける。三項演算子が使える。

模範解答
const scores = [82, 45, 91];
const list = document.querySelector("#list");

for (const s of scores) {
  const li = document.createElement("li");
  li.textContent = `${s}点`;
  li.classList.add(s >= 60 ? "pass" : "fail");
  list.appendChild(li);
}
解説

データの中身によって見た目を変える典型パターン。色の指定はCSS側に .pass { color: green; } と書いておけば、JavaScriptは判定に専念できる。

JS11-S03 【要素が無い場合に備える】id が "missing" の要素(存在しない)を取得し、あれば文字を書き換え、無ければ「要素が見つかりません」と出力せよ。そのあと id が "title" の要素(存在する)で同じ処理を行い「更新しました」と出力すること。 コーディング★★☆無料
期待される結果

出力2行。要素が見つかりません / 更新しました

ヒント

取得結果が null かどうかを if で判定する。関数にすると2回書かずに済む。

模範解答
const update = (selector, text) => {
  const el = document.querySelector(selector);

  if (el === null) {
    console.log("要素が見つかりません");
    return;
  }

  el.textContent = text;
  console.log("更新しました");
};

update("#missing", "新しい文字");
update("#title", "新しい文字");
解説

取得できたか確認してから操作するのが安全な書き方。null チェックを省くと Cannot set properties of null というエラーでページ全体が止まる。

JS11-S04 【表を組み立てる】users = [{ name: "田中", dept: "営業" }, { name: "鈴木", dept: "開発" }] から、tr の中に td を2つ持つ行を作り、id が "tbody" の要素に追加せよ。 コーディング★★★無料
期待される結果

#tbody に tr が2つ、各 tr に td が2つ

ヒント

tr を作り、その中に td を2つ appendChild してから、tr を tbody に appendChild する。入れ子の構造をそのままコードにする。

模範解答
const users = [
  { name: "田中", dept: "営業" },
  { name: "鈴木", dept: "開発" },
];

const tbody = document.querySelector("#tbody");

for (const u of users) {
  const tr = document.createElement("tr");

  const tdName = document.createElement("td");
  tdName.textContent = u.name;
  tr.appendChild(tdName);

  const tdDept = document.createElement("td");
  tdDept.textContent = u.dept;
  tr.appendChild(tdDept);

  tbody.appendChild(tr);
}
解説

HTMLの入れ子構造がそのままコードの入れ子になる。tr に td を入れてから tbody に入れる——この順序を守れば、どんな複雑な構造でも組み立てられる。

JS11-S05 【一覧の再描画】id が "list" に既に li が3つある状態から、いったん中身を空にして、newItems = ["A", "B"] で作り直せ。最後に「2件を表示しました」と出力すること。 コーディング★★★無料
期待される結果

#list の子要素が2つになり、出力 == 2件を表示しました

ヒント

中身を空にするには list.innerHTML = "" と書く。そのあと新しい要素を追加していく。

模範解答
const list = document.querySelector("#list");
const newItems = ["A", "B"];

list.innerHTML = "";

for (const item of newItems) {
  const li = document.createElement("li");
  li.textContent = item;
  list.appendChild(li);
}

console.log(`${newItems.length}件を表示しました`);
解説

再描画は「全部消してから作り直す」のが最も簡単で確実。innerHTML = "" は空文字を入れるだけなので、この用途ならXSSの心配もない。差分だけ更新する方法もあるが、複雑になるので規模が大きくなってから考えればよい。

5仕上げ課題

JS11-FINAL 【在庫一覧の画面を作る】データから在庫一覧の画面を組み立てよ。

const products = [
 { name: "ボールペン", stock: 120 },
 { name: "ノート", stock: 8 },
 { name: "消しゴム", stock: 45 },
 { name: "ファイル", stock: 3 },
];
const threshold = 10;


HTMLには #list(ul)と #summary(p)があるものとする。

仕様:
#list の中身をいったん空にする
② 各商品について li を作り、文字は「ボールペン:120個」の形式
③ 在庫が threshold 未満の商品には "low" クラスを付け、文字の末尾に「 ⚠発注」を足す
④ すべての li に "item" クラスを付ける
#summary に「全4品目 / 要発注2品目 / 総在庫176個」と表示する
⑥ 最後に「描画完了:4件」と出力する

期待される結果:li が4つ作られ、うち2つに low クラスが付く。summary に集計が入る。
期待される結果

li 4つ・low 2つ・summary の文言・出力1行

ヒント

合計は reduce、要発注の件数は filter で数えられる(JS09)。li の文字は三項演算子でマークを足す。クラスは classList.add("item") を全件に、条件付きで "low" を追加する。

模範解答
const products = [
  { name: "ボールペン", stock: 120 },
  { name: "ノート", stock: 8 },
  { name: "消しゴム", stock: 45 },
  { name: "ファイル", stock: 3 },
];
const threshold = 10;

const list = document.querySelector("#list");
const summary = document.querySelector("#summary");

list.innerHTML = "";

for (const p of products) {
  const li = document.createElement("li");
  const isLow = p.stock < threshold;

  li.textContent = `${p.name}:${p.stock}個${isLow ? " ⚠発注" : ""}`;
  li.classList.add("item");

  if (isLow) {
    li.classList.add("low");
  }

  list.appendChild(li);
}

const lowCount = products.filter((p) => p.stock < threshold).length;
const totalStock = products.reduce((sum, p) => sum + p.stock, 0);

summary.textContent = `全${products.length}品目 / 要発注${lowCount}品目 / 総在庫${totalStock}個`;

console.log(`描画完了:${products.length}件`);
解説

ここまで console.log に出していた在庫レポートが、ついに画面になった。JS06・JS07・JS09で何度も書いた同じデータが、今度はHTMLとして組み上がっている。

重要なのはデータと表示が分離していることだ。products の中身を変えるだけで画面が変わり、色やレイアウトを変えたければCSSの .low を直すだけでよい。JavaScriptは「何を表示するか」だけを担当し、「どう見せるか」はCSSに任せる——この分担が、大きなWebアプリでも破綻しない設計の基本になる。

ただし今の画面は一度描いたら終わりで、ユーザーが何をしても反応しない。次章のイベント処理を学ぶと、ボタンを押す・文字を入力するといった操作に応じて画面が動くようになる。