LLM注意

Claude Opus 4.6のチャットさんとの勉強会まとめです。

DOM操作について

そもそもDOMって何ぞ?

「Document Object Model」の頭文字を取った略語。
HTML「文書(=ドキュメント)」を対象にしているという意味。

つまりDOM操作では、実際にブラウザに表示されているアレやコレやソレを操作しちゃうのである。
うまくいくとテンションが上がるやつ。

ただし、001-Webアプリとは・JavaScript周辺の基礎単語でも書いた通り、HTMLをしっかり書けていないとそもそもの遊ぶための舞台(上述の「アレ」「ソレ」「コレ」に該当する、操作対象)がないということに。
HTMLに詳しいと得をしそうなお話。

基本操作の一つ、IDをつけた対象をいじる

<p id="output">ここに結果が出ます</p>

こんな感じでHTMLファイルのタグ要素の中にIDを設定する。
コレだけだとただのIDが目印な文字列の段落。

そこに004-JavaScriptの関数・配列・オブジェクト(ランダムを添えて)で使用した以下の関数を利用し、

const cards = [
  { name: "太陽", meaning: "希望と成功" },
  { name: "月", meaning: "不安と直感" },
  { name: "星", meaning: "癒しと導き" }
];
 
function drawCard(deck) {
  const index = Math.floor(Math.random() * deck.length);
  return deck[index];
}

以下の操作を指定する。

const result = drawCard(cards);
document.getElementById("output").textContent = result.name + ":" + result.meaning;

ドキュメントで始まると、HTML「ドキュメント」を触る合図。
そこにgetElementById()が丸括弧内のIDがついた要素を見つけに行くぜ!と宣言している。
つまり上述した、以下の段落をまるっと。

<p id="output">ここに結果が出ます</p>

そして.textContent = 〇〇で、段落まるっと、中身のテキストを差し替える。

今回はresult.name + ":" + result.meaningという指定なので、ドローカードの関数で得た結果(配列からランダムな順番で選んだオブジェクト)のプロパティ毎に内容の文字列を コロン を挟みつつ足し算……つまり連結表示みたいなことをさせようとしている。
(セミコロンとコロンの区別を間違え倒したので太字扱い)

実際にブラウザで表示させると「ここに結果が出ます」の文字列が「太陽:希望と成功」などの結果に差し代わっている。

なお、IDを変えれば様々な要素の表示に対応するため、

<dl>
    <dt id="cardname">カード名</dt>
    <dd id="cardmeaning">カードの説明</dd>
</dl>
const result = drawCard(cards);
document.getElementById("cardname").textContent = result.name;
document.getElementById("cardmeaning").textContent = result.meaning;

なんてプロパティ毎にサイトのあちこちに埋めることもできてしまうのである。

なお、textContentに指定した文字列については、ブラウザが「 ただの文字 」としてHTMLタグだろうがクォートの中のクォートだろうがそのまま表示するらしいので、コレを使ってタグの入れ子構造を作ることはできないようだ。

イベントについて

クロードさんの指示で、まずHTML側にボタンを作成。

<button id="draw-button">カードを引く</button>

もう見るからに怪しげなIDとボタンの文面である。

そして渡されるコレ。

document.getElementById("draw-button").addEventListener("click", function() {
  // ここに「押されたときにやること」を書く
});

どう見ても怪しい。

addEventListenerの直訳は出来事に耳を澄ませている相手を足す、である。
つまり出来事待ち状態を作り、そこにクリックが来たら関数を起動させる。多分functionの丸括弧がそう言っている。
すなわちdraw-buttonのIDがついたボタンにクリック待ちをさせている状態。

ここに、さっきDOM操作の勉強で作った以下の操作を入れる。

const result = drawCard(cards);
document.getElementById("cardname").textContent = result.name;
document.getElementById("cardmeaning").textContent = result.meaning;

すると最終的に、以下のように、ボタンを押す事で3種類のカードから1枚ランダムで引けるサイトが作れてしまったのである。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>JS練習</title>
</head>
<body>
  <h1>JavaScript練習場</h1>
  <button id="draw-button">カードを引く</button>
  <dl>
    <dt id="cardname">カード名</dt>
    <dd id="cardmeaning">カードの説明</dd>
  </dl>
  <script>
    const cards = [
      { name: "太陽", meaning: "希望と成功" },
      { name: "月", meaning: "不安と直感" },
      { name: "星", meaning: "癒しと導き" }
    ];
 
	function drawCard(deck) {
      const index = Math.floor(Math.random() * deck.length);
      return deck[index];
    }
 
    document.getElementById("draw-button").addEventListener("click", function() {
	  const result = drawCard(cards);
	  document.getElementById("cardname").textContent = result.name;
	  document.getElementById("cardmeaning").textContent = result.meaning;
    });
  </script>
</body>
</html>

因みに、ボタンを押すと都度都度中身をやり直してくれる。
つまり、中身が変わる。
すごい。

予習:JSONについて

次回以降、実際にこの仕組みを使ってオラクルカードを引くサイトを作ってみることになる、と聞いて、ふと。

今まで占いアプリとか占いbotとか作る時、カードデッキのデータはjsonとかいうファイル形式で渡していたな……? なーんて思い出してしまったのですよ。
これをまたオブジェクトのある配列として書き直すのかな? と。

で、クロードさんに聞いてみた結果。

なんと、 JSONは「JavaScript Object Notation」の頭文字 から来たデータ形式だった……!!

オブジェクトつきの配列などについて、変数の宣言や関数みたいなプログラム的部分を亡き者にしてしまったデータだけのファイル、それがJSONなのだそう。

const cards = [
  { name: "太陽", meaning: "希望と成功" },
  { name: "月", meaning: "不安と直感" },
  { name: "星", meaning: "癒しと導き" }
];

これをJSONにすると

[
  { "name": "太陽", "meaning": "希望と成功" },
  { "name": "月", "meaning": "不安と直感" },
  { "name": "星", "meaning": "癒しと導き" }
]

なのだそうで、忘れちゃいけないのが JSONではプロパティもクォートで囲っておく こと。

NOTE

逆にJavaScriptのオブジェクトつき配列のプロパティにうっかりクォートをつけた場合、動くのは動くらしいのだけれど、だからと言って「そんな区別覚えてられないから全部クォートつけるぜ!」にはならないとのこと。

JavaScriptでオブジェクトつき配列を書くときはプロパティにクォートをつけないのがマナーっぽいです。

JSONの便利ポイントはプログラム部分とデータ部分を分ける事で、データ部分だけ後から編集しやすいこと。
確かに、プログラム本体そっちのけでJSONを編集できるのは、便利だった思い出。

一方で、外部のJSONをJavaScriptで使おうとすると 非同期処理 という少しややこしい(JSONの中身を取りに行っている間待つという)仕組みが必要で、それは今後の講座に登場予定とのこと。