Javaを学び終えた新人エンジニアのみなさんがJavaScriptを学ぶことには、以下の4つの意義があります。

  1. フロントエンド開発への応用力が高まる
     Javaが主にサーバーサイドで利用されるのに対し、JavaScriptはフロントエンド開発に欠かせない言語です。JavaScriptを習得することで、より広い技術分野において知識を有するエンジニアとしてシステム全体を設計・実装できるようになり、技術の幅が大きく広がります。
  2. 設計思想の違いを理解できる
     Javaは静的型付け言語で、型が厳密にチェックされるのに対し、JavaScriptは動的型付け言語で柔軟に記述できます。この違いはバグの出方や設計手法にも影響します。異なる型システムに触れることで、より柔軟かつ堅牢なコード設計が可能になります。また、Javaはコンパイラ型で事前にバイトコードに変換され、JavaScriptはインタプリタ型で逐次実行されます。こうした実行モデルの違いを知ることで、アプリケーションの性能や開発体験にも敏感になり、適切な技術選定ができるようになります。
  3. TypeScriptやNode.jsを通じて、フルスタック開発に対応できる
     JavaScriptの知識をさらに広げると、型安全性を持つTypeScriptや、JavaScriptでサーバーサイド開発を可能にするNode.jsといった技術に触れることができます。これにより、Javaの知識と組み合わせてフロントエンドからバックエンドまで一貫したシステム開発が可能になり、現代の開発現場で重宝される存在になれます。

JavaScriptを学ぶことで、視野が広がり、より多角的な開発スキルを身につけることができるのです。

この講座の目標

以下の名前入力フォームのJavaScript部分を読んで何をしているのかが理解できるレベルを目指します。

JavaScriptを使ったWebページには以下のような一定の型があります。

「DOM要素を取得→イベントを登録→繰り返しや条件分岐→表示更新」

document.addEventListener('DOMContentLoaded', () => {
  // ① DOM要素の取得
  const form = document.getElementById('signup-form');
  const usernameInput = document.getElementById('username');
  const message = document.getElementById('message');

  // ② フォーム送信時の処理
  form.addEventListener('submit', (e) => {
    e.preventDefault(); // ページのリロードを防止

    const name = usernameInput.value.trim();

    // ③ 入力チェック
    if (name === '') {
      showMessage('名前を入力してください', 'error');
      return;
    }

    // ④ 成功メッセージの表示
    showMessage(`ようこそ、${name}さん!`, 'success');

    // ⑤ フォームのリセット(任意)
    form.reset();
  });

  // ⑥ メッセージ表示用の関数
  function showMessage(text, type) {
    message.textContent = text;
    message.className = `message ${type}`; // class を上書き
  }
});
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>名前入力フォーム</title>
  <link rel="stylesheet" href="styles.css" />
</head>
<body>
  <h1>ユーザー登録</h1>
  <form id="signup-form">
    <label for="username">名前:</label>
    <input type="text" id="username" />
    <button type="submit">送信</button>
  </form>
  <p id="message" class="message"></p>

  <script src="script.js"></script>
</body>
</html>
.message {
  margin-top: 10px;
  padding: 8px;
  display: inline-block;
}
.success {
  color: green;
  border: 1px solid green;
}
.error {
  color: red;
  border: 1px solid red;
}

JavaScriptはボディの閉じタグの直前に書かれることが一般的です。HTMLを読み込んだあとに実行したいためです。

1. DOMを操作するJavaScriptの定番の流れ

① DOMの読み込みを待つ(必須)

document.addEventListener('DOMContentLoaded', () => {
  // ここに初期化処理を書く
});

  • HTMLが完全に読み込まれる前にJavaScriptが実行されると、要素が取得できないことがある。
  • そのため、初期処理はDOMContentLoadedイベントで囲むのが安全。

② DOM要素を取得する

const button = document.getElementById('submit-button');
const input = document.querySelector('#name');

  • 目的の要素にアクセスするためにgetElementByIdquerySelectorで取得。
  • 変数名は「何を操作するか」がわかるようにするのが定番

③ イベントリスナーを登録する

button.addEventListener('click', () => {
  // クリック時の処理
});

  • 典型的なユーザー操作(クリック、入力、送信など)に対応。
  • コールバック関数はアロー関数でその場に書くか、別関数に切り出して再利用する

④ 状態に応じた処理を行う(検証、条件分岐など)

if (input.value.length < 5) {
  alert('5文字以上入力してください');
}

  • DOMから取得した値を検証し、分岐処理を実行
  • 状態に応じて表示要素を書き換える処理などが続く。

⑤ DOMの見た目や中身を更新する

document.querySelector('#message').textContent = '送信完了';
document.querySelector('#message').classList.add('visible');

  • textContent, innerHTML, classList, styleなどで表示を操作
  • 特に最近はクラスのON/OFFで状態を切り替える手法が一般的。

2. 関数宣言

Javaのメソッドはクラスに属し、型やアクセス修飾子が必須でした。一方JavaScriptの関数は独立して定義でき、アロー関数ではfunctionキーワードすら不要で簡潔です。

特にアロー関数は「外側のスコープのthisを引き継ぐ」特徴があり、コールバック関数やイベント処理で便利です。通常の関数ではthisは呼び出し元に依存しますが、アロー関数では定義時のthisを保持するため、クラス内やDOM操作での意図しないthisの変化を防げます。Javaでは常にthisは自身のインスタンスを指すのと対照的です。

調べてみましょう

コールバック関数とは、他の関数に引数として渡され、特定のタイミングで呼び出される関数のことです。処理の完了後やイベント発生時などに実行されるため、非同期処理やイベント処理でよく使われます。アロー関数で書くこともできます。余裕があればコールバック関数について調べてみましょう。

JavaScriptでは関数を宣言する方法が複数あり、主に以下の2つが使われます。


1. 関数宣言(Function Declaration)

function greet() {
  console.log('Hello');
}

特徴

  • 巻き上げ(Hoisting)される
    → スクリプト内で定義より前でも呼び出せる
  • よりグローバルやロジックの基本部分に向いている

使うべき場面

  • 明確に何度も呼び出す処理を定義したいとき。
  • コード構造を読みやすく整理したいとき
  • イベント外などスコープの最上位で使いたいとき

2. 関数式(Function Expression)

const greet = function () {
  console.log('Hello');
};

またはアロー関数で:

const greet = () => {
  console.log('Hello');
};

特徴

  • Hoistingされない
    定義より前では呼び出せない
  • constlet と組み合わせて、関数を変数に代入できる。

使うべき場面

  • イベントリスナーのようにその場で関数を渡す場合
  • スコープを限定したい処理(モジュール内や関数内など)。
  • 関数を値として扱う処理(例:コールバック、配列処理map, filterなど)。

まとめ(理解のポイント)

項目関数宣言関数式(アロー含む)
巻き上げされるされない
再利用性高い(複数箇所で使う)低い(使い捨てが多い)
スコープの制御あまり強くないconst/letと合わせて制御できる
主な用途汎用的な処理イベント・コールバック・クロージャ

何をどこで使うのかによって、「使い捨て」か「再利用」かを意識して選ぶと良いでしょう。

「アロー関数」の作り方をステップバイステップで

✅ ステップ 0:従来の関数(function宣言)を確認

JavaSEを学んだ皆さんなら見慣れた形だと思います。ただし、戻り値や引数の型は書きません。

function sayHello(name) {
  return 'こんにちは、' + name + 'さん!';
}


✅ ステップ 1:アロー関数の基本構文を覚える
const 関数名 = (引数) => {
処理;
return 戻り値;
};

たとえば先ほどのsayHello関数はこう書き換えられます:

const sayHello = (name) => {
  return 'こんにちは、' + name + 'さん!';
};


✅ ステップ 2:引数が1つならカッコを省略できる
const sayHello = name => {
  return 'こんにちは、' + name + 'さん!';
};


✅ ステップ 3:処理が「return だけ」の場合、波かっこと return を省略できる
const sayHello = name => 'こんにちは、' + name + 'さん!';

🔹 これがアロー関数の最も省略された書き方です!


✅ ステップ 4:引数がない場合は () を使う
const greet = () => 'やあ!';


✅ ステップ 5:複数行の処理がある場合は {}return を使う
const sum = (a, b) => {
  const result = a + b;
  return result;
};


✅ ステップ 6:オブジェクトを返すときは () で囲む
const getUser = () => ({ name: 'Yusei', age: 25 });

return { name: 'Yusei' } のように見えてしまうと「波かっこ=関数のブロック」と勘違いされるため、オブジェクトリテラルは括弧で包む必要があります


第1章 JavaScriptとは?

1-1. JavaScriptの立ち位置を理解しよう

JavaScriptは、Webページに動きを与えるためのプログラミング言語です。HTMLやCSSが「構造」と「見た目」を担当するのに対し、JavaScriptはユーザーの操作に応じたインタラクティブな動作を実現します。

Web開発の三本柱

技術役割
HTML構造見出し、段落、リンクなど
CSS見た目色、フォント、レイアウト
JavaScript動き・機能ボタンクリック時の処理、入力チェック、アニメーション

これらを組み合わせることで、モダンなWebアプリケーションが実現されています。


1-2. フロントエンドとバックエンドの違い

フロントエンド

  • ユーザーが直接見る部分(ブラウザ上で表示されるHTML/CSS/JavaScript)
  • JavaScriptで実装される処理:ボタンクリック、バリデーション、非同期通信など

バックエンド

  • サーバー側で動作する処理(Java, Python, PHP など)
  • Spring Bootなどのフレームワークが使われる

【例】
フォームに入力 → JavaScriptで入力チェック → サーバーに送信 → Spring Bootがデータを処理 → 結果を画面に表示

フロントエンドとバックエンドは、役割分担して連携しています。


1-3. JavaとJavaScriptは全くの別物!

名前は似ていますが、JavaとJavaScriptは全く異なる言語です。

比較項目JavaJavaScript
実行環境JVM(サーバー、PCなど)Webブラウザ
用途サーバー処理、業務アプリ等Webの画面処理、動的なUI
型付け静的型付け動的型付け
クラスベースES6からはクラスあり(本質はプロトタイプ)

Javaの経験があると、文法面で親しみやすい部分はありますが、根本的な考え方が違うため、最初は混乱しないように注意が必要です。


1-4. JavaScriptはブラウザで動く!

JavaScriptの最大の特徴は「ブラウザ上で即時実行できる」ことです。

ブラウザに組み込まれたJavaScriptエンジン

  • Chrome → V8エンジン
  • Firefox → SpiderMonkey
  • Safari → JavaScriptCore(Nitro)

つまり、インストール不要で、すぐに試せるのが魅力です。開発者ツール(F12)を使えば、その場でコードを試せます。

<!-- HTMLに直接JavaScriptを埋め込む例 -->
<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
</head>

<body>
	<button onclick="alert('こんにちは')">クリックしてみて!</button>
</body>

</html>

第2章 JavaScriptの基本文法

2-1. 変数の宣言とスコープ

JavaScriptでは、変数を次の3つのキーワードで宣言できます。

let:ブロックスコープの変数

let count = 5;
count = count + 1; // OK

const:再代入不可の定数

const name = "Yamazaki";
// name = "Tanaka"; // エラー!

var:昔の書き方(関数スコープ)→ 非推奨

var oldVar = 10; // 古い書き方、基本使わない

英語の意味から解説

「let」は「~させて」という英語の意味を持ち、「あとから中身を変更できる変数」を作るときに使います。

「const」は「constant(コンスタント)=一定のもの」の略で、一度決めたら値を変えられない定数に使います。

「var」はvariable(変数)の略です。昔よく使われていたためインターネット上の記事を読むときは注意しましょう。

グローバルスコープとローカルスコープ

グローバルスコープ

関数やブロックの外で宣言された変数は、どこからでもアクセスできるグローバルスコープになります。特にconstletでグローバルに宣言した変数は、スクリプト全体で使えます。

const globalVar = "全体で使える";

function show() {
  console.log(globalVar); // 参照できる
}

ローカルスコープ(関数スコープ・ブロックスコープ)

関数の中や、ifforなどのブロック内で宣言された変数は、その内部でのみ有効です。他からは参照できません。

function example() {
  let localVar = "ここだけ有効";
  console.log(localVar);
}

// console.log(localVar); // エラー:外からは見えない

Javaとの違い

Javaは静的型付けなのですべての変数に明示的な型宣言(例: int, String)が必要ですが、JavaScriptは 動的型付け なので、letconst だけで柔軟に宣言できます。



2-2. データ型の基本

主なプリミティブ型

型名備考
数値(Number)42, 3.14整数・小数の区別なし
文字列(String)"Hello", 'Hi', `ようこそ`シングル・ダブル・バッククォート
真偽値(Boolean)true, false条件分岐でよく使う
未定義(undefined)未代入の変数let x; console.log(x); // undefined
null値が存在しないことを明示let user = null;
let age = 25;
let name = "Yamazaki";
let isMember = true;


2-3. 演算子

算術演算子

let a = 5 + 2;    // 7
let b = 5 - 2;    // 3
let c = 5 * 2;    // 10
let d = 5 / 2;    // 2.5(Javaとの違い)
let e = 5 % 2;    // 1(剰余)

比較演算子

3 == "3"   // true(型が違ってもOK)
3 === "3"  // false(型も比較 → これを推奨!)
5 !== 4    // true

Javaとの違い

==は型変換あり、===は型も一致。基本的に===!==を使うようにしましょう。


論理演算子

true && false  // AND(→ false)
true || false  // OR(→ true)
!true          // NOT(→ false)


2-4. テンプレート文字列

JavaScriptでは、変数を文字列に埋め込むとき、バッククォート `を使ったテンプレートリテラルが便利です。

let name = "Yamazaki";
let age = 30;
let message = `名前は${name}、年齢は${age}歳です。`;
console.log(message);
// → 名前はYamazaki、年齢は30歳です。

Thymeleafのテンプレート文字列との共通点と相違点

共通点${} を使って変数や式を埋め込むこと、コードが直感的でわかりやすくなる点。

相違点:処理される場所(JavaScriptはブラウザ上、Thymeleafはサーバー上)、文法や適用範囲、使用目的に違いがあります。





第3章 制御構文と関数

3-1. 条件分岐(if / else if / else)

Javaと同様に、条件に応じた処理を分けることができます。

let score = 85;

if (score >= 90) {
  console.log("とても良くできました!");
} else if (score >= 70) {
  console.log("よくできました!");
} else {
  console.log("がんばりましょう!");
}

条件式のかっこ ( ) やブロック { } の書き方はJavaと同じです。


3-2. switch文

複数の分岐条件を判定するときに使います。

let fruit = "apple";

switch (fruit) {
  case "apple":
    console.log("リンゴです");
    break;
  case "banana":
    console.log("バナナです");
    break;
  default:
    console.log("その他の果物です");
}

  • break を忘れると下まで実行されてしまうので注意!

3-3. 繰り返し処理(for / while)

for文

for (let i = 0; i < 5; i++) {
  console.log(`iは${i}`);
}

Javaとほぼ同じ構文です。

while文

let count = 0;
while (count < 3) {
  console.log(count);
  count++;
}


3-4. for...of文(配列の繰り返し)

JavaScriptには、配列の要素を簡単に取り出す構文があります。

const fruits = ["apple", "banana", "orange"];

for (const fruit of fruits) {
  console.log(fruit);
}

Javaの「拡張for文」に似た感覚で使えます。


3-5. 関数の定義と呼び出し

通常の関数定義(function宣言)

function greet(name) {
  return `こんにちは、${name}さん!`;
}

console.log(greet("Imai")); // → こんにちは、Imaiさん!

関数式(変数に代入:無名関数)

const greet = function(name) {
  return `こんにちは、 ${name}さん`;
};

アロー関数(ES6以降の書き方:無名関数)

const greet = (name) => {
  return `こんにちは、 ${name}さん`;
};

1行だけなら波かっこ・returnも省略可能:

const greet = name => `こんにちは、${name}さん`;


3-6. スコープ(変数の有効範囲)

JavaScriptでは関数の内外でスコープ(見える範囲)が異なります

let x = 10;

function sample() {
  let y = 5;
  console.log(x); // 10(外の変数は見える)
}
console.log(y); // エラー!(関数内の変数は外から見えない)

letconstブロックスコープ。Javaと似た感覚で扱えます。

第4章 配列とオブジェクトの基本

4-1. 配列(Array)とは?

配列は、複数の値を順番に格納するためのデータ構造です。JavaでいえばArrayListに似ています。JavaScriptでは、次のように定義します。

const fruits = ["apple", "banana", "orange"];
console.log(fruits[0]); // apple(0番目)
  • 添字(インデックス)は 0 から始まります(Javaと同じ)
  • 異なる型の要素も混在できます(ただしあまり推奨されません)
const mixed = [1, "hello", true]; // 数値、文字列、真偽値


4-2. 配列の主な操作

要素の追加・削除

let animals = ["dog", "cat"];
animals.push("rabbit");     // 末尾に追加
animals.pop();              // 末尾を削除
animals.unshift("lion");    // 先頭に追加
animals.shift();            // 先頭を削除

繰り返し処理(forEach, map)

const numbers = [1, 2, 3];
numbers.forEach(num => {
  console.log(num * 2); // 2, 4, 6
});

const doubled = numbers.map(num => num * 2); // [2, 4, 6]

参考アロー関数を使わない forEach

const numbers = [1, 2, 3];

numbers.forEach(function(num) {
  console.log(num * 2); // 2, 4, 6
});


参考アロー関数を使わない map

const doubled = numbers.map(function(num) {
  return num * 2;
});

console.log(doubled); // [2, 4, 6]


配列の長さ、検索、結合など

const fruits = ["apple", "banana"];
console.log(fruits.length);     // 配列の長さ(2)
console.log(fruits.includes("banana")); // true
console.log(fruits.join(", ")); // "apple, banana"

4-3. オブジェクト(Object)とは?

オブジェクトは、名前(キー)と値のセットを持つデータ構造です。JavaのMap<String, Object>のようなイメージです。

const user = {
  name: "Imai",
  age: 30,
  isMember: true
};
console.log(user.name);    // Imai
console.log(user["age"]);  // 30(どちらの書き方も可)


4-4. オブジェクトの操作

プロパティの追加・更新・削除

user.email = "Yamazaki@example.com";  // 追加
user.age = 31;                      // 更新
delete user.isMember;              // 削除

オブジェクトのループ処理(for...in)

for (const key in user) {
  console.log(`${key}: ${user[key]}`);
}

4-5. 配列×オブジェクトの組み合わせ

現実のWeb開発では、オブジェクトの配列を扱う場面が多いです。例えばユーザー一覧、商品一覧など。

const users = [
  { name: "Imai", age: 30 },
  { name: "Matsuda", age: 25 },
];

users.forEach(user => {
  console.log(`${user.name}(${user.age}歳)`);
});

4-6. オブジェクトの分割代入(Destructuring Assignment)

オブジェクトの中から特定のプロパティを変数として取り出す簡潔な書き方が「分割代入」です。

const user = {
  name: "Imai",
  age: 30,
  isMember: true
};

// 通常の書き方
const name = user.name;
const age = user.age;

// 分割代入を使うとより簡潔に書ける
const { name, age } = user;
console.log(name); // "Imai"
console.log(age);  // 30

また、プロパティ名を変えたい場合は「:(コロン)」を使って別名をつけることもできます。

const { name: userName, age: userAge } = user;
console.log(userName); // "Imai"
console.log(userAge);  // 30

よくある用途

  • 関数の引数で使って、受け取るプロパティだけ抜き出す
  • 複雑なデータ構造でも、コードがすっきりして読みやすくなる
function showUser({ name, age }) {
  console.log(`${name}さんは${age}歳です`);
}

showUser(user); // Imaiさんは30歳です

次章は、Spring Boot + Thymeleafの画面にJavaScriptを組み込むために不可欠な「DOM(Document Object Model)」を解説します。

第5章 DOM操作の基礎

DOMってなに?

まず、「DOMって何?」というところからはじめましょう。

DOM(Document Object Model)は、Webページをオブジェクトとして扱う仕組みのことです。

たとえば、次のようなHTMLがあったとします。

<body>
  <h1 id="title">Hello</h1>
</body>

これをJavaScriptで操作するには、「document」というオブジェクトを使って、まるで「木の枝をたどるように」要素にアクセスします。


代表的なDOM組み込みオブジェクト一覧

オブジェクト名役割・用途
windowブラウザのウィンドウ全体を表す
documentWebページ(HTMLドキュメント)全体を表す
ElementHTMLの要素(タグ)を表す
NodeDOMツリーのノードを表す(テキストなども含む)
NodeListノードの一覧(配列っぽいけど配列ではない)
HTMLCollectionHTML要素のコレクション(これも配列ではない)
Eventイベントオブジェクト(クリック・キーボードなど)
HTMLElement特定のHTML要素型の親クラス(例:HTMLDivElement

それぞれを詳しく解説!

1. windowオブジェクト

JavaScriptの最上位オブジェクトで、ブラウザのタブそのものを指します。

console.log(window.innerWidth); // ウィンドウの幅

ちなみに、alert()setTimeout() なども window.alert() の省略形です!


2. documentオブジェクト

window.document は、Webページの内容そのもの(HTMLドキュメント)を指します。

document.getElementById("title").textContent = "こんにちは!";

ページ内の要素にアクセスする入り口です!


3. Elementオブジェクト

これは、HTMLのタグ1つ1つを表すオブジェクトです。

let el = document.querySelector("h1");
el.style.color = "red";

ElementHTMLElement の親クラスにあたります。


4. Nodeオブジェクト

DOMの構造は「ノード(節)」として表現されます。

  • <div>要素ノード
  • "こんにちは"テキストノード

というように、すべての要素や文字列が「ノード」として扱われます。

let node = document.getElementById("title").childNodes[0];

NodeElement よりも広い概念です。


5. NodeListとHTMLCollectionの違い

どちらも複数の要素を格納した「配列っぽいもの」ですが、違いに注意!

特徴NodeListHTMLCollection
作られる関数例querySelectorAll()getElementsByTagName()など
更新される?いいえ(静的)はい(動的)
forEach使える?使える(モダンブラウザ)使えない

6. Eventオブジェクト

クリックやキーボード入力など、イベントの情報を保持するオブジェクトです。

document.addEventListener("click", function(event) {
  console.log(event.target); // クリックされた要素
});

event という引数は、イベントに関するすべての情報を含んでいます。

7. HTMLElementとそのサブクラスたち

HTMLElement は、すべてのHTML要素の共通の型であり、さらに具体的な要素ごとに次のようなクラスがあります。

クラス名対応するHTML要素
HTMLDivElement<div>
HTMLInputElement<input>
HTMLButtonElement<button>
let btn = document.querySelector("button");
console.log(btn instanceof HTMLButtonElement); // true


DOMの階層構造:図でイメージしよう

window
 └─ document
     └─ <html>
         └─ <body>
             ├─ <h1>
             │   └─ TextNode ("Hello")
             └─ <p>
                 └─ TextNode ("Welcome")

このように、ツリー構造(木構造)になっているのがDOMの特徴です。


よくある操作例:実践で使える!

要素を取得する

document.getElementById("title")
document.querySelector(".item")

要素を作る・追加する

let p = document.createElement("p");
p.textContent = "新しい段落";
document.body.appendChild(p);

クラスやスタイルを変更する

el.classList.add("active");
el.style.backgroundColor = "blue";

例:以下のようなHTMLがあるとします

<h1 id="title">こんにちは</h1>

→ これはJavaScriptから次のようにアクセスできます:

const heading = document.getElementById("title");
heading.textContent = "ようこそ!";


5-2. 要素の取得方法

DOM操作の第一歩は、対象となるHTML要素を取得することです。

document.getElementById(id)

  • idが付いた要素を1つ取得します(最速でシンプル)
<p id="message">Hello</p>

const msg = document.getElementById("message");

document.querySelector(cssセレクタ)

  • CSSセレクタで要素を1つ取得します(汎用的)
<p class="text">こんにちは</p>

const text = document.querySelector(".text");

document.querySelectorAll(cssセレクタ)

  • 複数の要素を一括で取得します(配列風オブジェクトが返る)
<ul>
  <li class="item">A</li>
  <li class="item">B</li>
</ul>

const items = document.querySelectorAll(".item");
items.forEach(item => console.log(item.textContent));


5-3. テキストやHTMLの変更

textContent:テキストのみ書き換える

heading.textContent = "ようこそ!";

innerHTML:HTMLごと差し替え(タグも書き換える)

div.innerHTML = "<strong>太字で表示</strong>";

innerHTML は柔軟ですが、ユーザー入力を直接代入するとXSS(セキュリティ問題)になりやすいため注意が必要です。


5-4. 属性やクラスの操作

属性を変更する:setAttribute, getAttribute

const link = document.querySelector("a");
link.setAttribute("href", "https://example.com");

クラスを追加・削除・切り替え:classList

element.classList.add("active");
element.classList.remove("hidden");
element.classList.toggle("selected");


5-5. 要素の追加・削除

要素を作成して追加する

const ul = document.querySelector("ul");
const li = document.createElement("li");
li.textContent = "新しい項目";
ul.appendChild(li);

要素を削除する

ul.removeChild(li); // 親から子を削除

または、直接 .remove() で削除することも可能(新しめの方法):

li.remove();


5-6. Spring Boot × DOM操作の注意点

Spring Boot + Thymeleafでは、テンプレートで生成されるHTMLにJavaScriptがアクセスする場合:

  • JavaScriptの読み込みはHTMLの末尾に配置(</body>直前)するのが原則
  • DOMがまだ読み込まれていないと、要素が null になるので注意!
<!-- OKな配置例 -->
<script src="/js/main.js"></script>
</body>
</html>

もしくは DOMContentLoaded イベントを使って、「ページの読み込み完了後」に処理を実行する方法もあります(次章で詳しく扱います)。


第6章 イベント処理の基本

6-1. イベントとは?

イベントとは、ユーザーの操作(クリック、入力、スクロールなど)に対してブラウザが発生させる「出来事」です。
JavaScriptではこのイベントに反応(リッスン)して、任意の処理を実行できます。

代表的なイベントの種類

イベント名発生タイミング
click要素がクリックされたとき
input入力欄の内容が変更されたとき
submitフォームが送信されたとき
changeセレクトボックスやチェックボックスが変更されたとき
DOMContentLoadedページのHTML読み込み完了時

6-2. addEventListener を使ったイベント登録

JavaScriptでは、addEventListener を使ってイベントを設定するのが基本です。

例:ボタンがクリックされたらメッセージを表示

<button id="myBtn">クリックしてね</button>

const btn = document.getElementById("myBtn");
btn.addEventListener("click", () => {
  alert("ボタンがクリックされました!");
});
  • 第1引数:イベント名(文字列)
  • 第2引数:実行する関数(イベントハンドラ)

6-3. event オブジェクトで詳細を取得

イベントハンドラの関数には、event オブジェクトが自動で渡されます。

btn.addEventListener("click", (event) => {
  console.log(event.target); // イベントが発生した要素
});

これを使えば、複数のボタンに1つの関数で対応することも可能です。


6-4. フォーム送信イベントと preventDefault()

フォーム送信(submitイベント)は、通常だとページ遷移やリロードが発生します。
JavaScriptで制御したい場合は、preventDefault() を使ってそれを止めます。

例:送信ボタンを押したらアラートを表示し、ページ遷移を防ぐ

<form id="form">
  <input type="text" name="username" />
  <button type="submit">送信</button>
</form>

const form = document.getElementById("form");

form.addEventListener("submit", (event) => {
  event.preventDefault(); // デフォルトの動作(送信)をキャンセル
  alert("フォームが送信されました!");
});


6-5. 入力イベントでリアルタイムに反応する

input イベント:テキスト入力のたびに呼び出される

<input id="nameInput" />
<p id="preview">こんにちは!</p>

const input = document.getElementById("nameInput");
const preview = document.getElementById("preview");

input.addEventListener("input", () => {
  preview.textContent = `こんにちは、${input.value}さん!`;
});

フォームの内容をリアルタイムに画面に反映させる例です。


6-6. よくあるパターン:ループ + イベント

複数の要素にイベントをまとめて設定することもよくあります。

<ul>
  <li class="item">Item 1</li>
  <li class="item">Item 2</li>
</ul>

const items = document.querySelectorAll(".item");

items.forEach(item => {
  item.addEventListener("click", () => {
    item.classList.toggle("selected");
  });
});

第7章 実践!Spring Bootアプリと連携するJavaScript

7-1. Spring BootとJavaScriptの関係

Spring Bootでは、@ControllerでHTMLテンプレート(Thymeleaf)を返し、そのHTMLに対してJavaScriptを使って動的な動きを付け加えるのが一般的です。

【例】
Controller → Thymeleaf → HTML表示 → JavaScriptでDOM操作やイベント処理

JavaScriptの主な役割:

  • 入力チェック(バリデーション)
  • フォームの補助入力やリアルタイム表示
  • 表示の切り替え(例:モーダル、エラーメッセージ)
  • ユーザーの操作ログの取得・確認

7-2. HTML要素とJavaScriptの連携方法

JavaScriptから要素を操作するには、idclassが重要な目印となります。Thymeleafとの組み合わせでは、以下のように書くことが多いです。

Thymeleafの中でid/classを使う

<input type="text" th:id="'nameInput'" th:value="${user.name}">
<p id="namePreview">ようこそ!</p>

const input = document.getElementById("nameInput");
const preview = document.getElementById("namePreview");

input.addEventListener("input", () => {
  preview.textContent = `こんにちは、${input.value}さん!`;
});

th:id を使うと Thymeleaf によってHTMLが生成されたあとでも JavaScript で操作可能になります。


7-3. 表示の切り替え(エラー表示、詳細表示など)

classの追加/削除で表示切り替え

<div id="errorBox" class="hidden">エラーがあります</div>

.hidden { display: none; }

const errorBox = document.getElementById("errorBox");
errorBox.classList.remove("hidden"); // 表示する

クラスを使った切り替えは、見た目を保ったまま制御できるので非常に実用的です。


7-4. 確認ダイアログ(削除ボタンの確認)

Spring Bootアプリでよくあるのが「削除ボタンの押し間違い防止」です。

<form th:action="@{/delete}" method="post" onsubmit="return confirmDelete();">
  <button type="submit">削除</button>
</form>

function confirmDelete() {
  return confirm("本当に削除してよろしいですか?");
}

confirm() はシンプルな組み込みダイアログです。


7-5. 動的リストの追加・削除

JavaScriptで動的に要素を追加する例

<ul id="todoList"></ul>
<input type="text" id="todoInput">
<button id="addBtn">追加</button>

const list = document.getElementById("todoList");
const input = document.getElementById("todoInput");
const addBtn = document.getElementById("addBtn");

addBtn.addEventListener("click", () => {
  const text = input.value;
  if (text.trim() !== "") {
    const li = document.createElement("li");
    li.textContent = text;
    list.appendChild(li);
    input.value = ""; // 入力欄をリセット
  }
});

このように、Spring Bootから表示された画面でも、ユーザーの入力内容を元に動的なリスト表示が実現できます。


7-6. 実務で使えるちょっとしたテクニック集

ページ読み込み後に処理を実行する方法

document.addEventListener("DOMContentLoaded", () => {
  console.log("ページが読み込まれました");
});

これは、要素を操作する前にDOMの読み込みを保証する安全な方法です。

data-属性 を活用したデータ埋め込み

Thymeleafでは、data-属性 を使ってサーバーからのデータをHTMLに埋め込んでおき、JavaScriptで拾うという手法もよく使われます。

<button class="deleteBtn" th:data-id="${item.id}">削除</button>

const btns = document.querySelectorAll(".deleteBtn");
btns.forEach(btn => {
  btn.addEventListener("click", () => {
    const id = btn.dataset.id;
    console.log(`削除対象のID: ${id}`);
  });
});

JavaScript研修、お疲れさまでした。

HTML/CSSとJavaの基礎を土台に、JavaScriptの文法からDOM操作、イベント処理、そしてSpring Bootとの連携までを駆け抜けた皆さんの努力は、これからの現場で確かな力になります。大切なのは、知識を「知っている」だけでなく「使ってみる」こと。疑問にぶつかったときこそ学びのチャンスです。これからも実践を重ね、チームやユーザーのために“動く画面”を作れるエンジニアとして、ますます活躍されることを心より願っています。

「JavaScript入門テキスト」 最後までお読みいただきありがとうございます。