基礎から学ぶJavaScript入門 90日コース | Webページを操作するDOM - Day 42:DOM操作演習

JavaScript 90日で身につけるJavaScript
スポンサーリンク
スポンサーリンク
  1. Day 42:DOM操作演習(前半)
  2. 簡易電卓の全体像をイメージする
    1. どんなUIの電卓を作るか
  3. HTMLで電卓の土台を作る
    1. 入力欄・演算子選択・結果表示を用意する
  4. JavaScriptでDOM要素を取得する
    1. 電卓に必要な要素を変数にまとめる
  5. 数字入力を“数値として扱う”ことを理解する
    1. 入力欄の値は文字列として取得される
    2. Number() で文字列を数値に変換する
  6. 計算ボタンにイベントを設定する
    1. clickイベントで「計算する」処理を呼び出す
  7. 入力値を取得してバリデーションする
    1. 入力値を取得する
    2. 入力値が空でないかチェックする
    3. 数値に変換して、数値かどうかをチェックする
  8. 四則演算を実装する
    1. 演算子に応じて計算方法を切り替える
  9. 結果を画面に表示する
    1. 結果表示エリアにテキストとして反映する
  10. 完成コード(コメント付き簡易電卓)
  11. 少しだけ発展させる:小数点や桁数の扱い
  12. セキュリティ・安全性の視点からの補足
  13. Day 42 前半 練習用テンプレート
  14. Day 42 前半のまとめ
  15. Day 42:DOM操作演習(後半)
  16. 電卓の“使い勝手”を考え直す
    1. どんな機能があると、ユーザーは使いやすいか
  17. HTMLを“完成形”に近づける
    1. クリアボタンと結果用のクラスを追加する
  18. JavaScriptでDOM要素と“状態”を整理する
    1. 必要なDOM要素を取得する
  19. 計算ロジックを関数にまとめる
    1. calculate() 関数で「入力 → バリデーション → 計算 → 結果表示」を一括管理する
  20. イベントから calculate() を呼び出す
    1. 計算ボタンのクリックで calculate() を実行する
    2. Enterキーでも計算できるようにする(発展)
  21. クリア機能(リセット)を追加する
    1. clear() 関数で入力と表示を初期状態に戻す
    2. クリアボタンにイベントを設定する
  22. 完成コード(コメント付き・発展版簡易電卓)
  23. 少しだけ発展させる:小数点と桁数の扱い
  24. セキュリティ・ユーザー体験の視点からのまとめ
  25. Day 42 後半 練習用テンプレート
  26. Day 42 後半のまとめ

Day 42:DOM操作演習(前半)

「簡易電卓を通して“入力 → 計算 → 結果表示”の流れを身につける」

Day 42前半では、DOM操作演習として 「簡易電卓」 を作成していきます。 電卓はとてもシンプルな題材ですが、

  • 数字入力
  • 四則演算(足し算・引き算・掛け算・割り算)
  • 結果表示

という、Webアプリでよく使う流れがぎゅっと詰まっています。

この演習を通して、

「ユーザーの入力を受け取り、JavaScriptで処理し、結果をDOMに反映する」

という一連のパターンを、自然に書けるようになることを目指します。

簡易電卓の全体像をイメージする

どんなUIの電卓を作るか

今回作る簡易電卓は、次のような構成にします。

  • 数字を入力するテキストボックスが2つ(数値A・数値B)
  • 演算子(+、−、×、÷)を選ぶセレクトボックス
  • 「計算する」ボタン
  • 結果を表示するエリア

イメージとしては、

「A(入力) 演算子 B(入力) = 結果」

という形の、シンプルな計算フォームです。

HTMLで電卓の土台を作る

入力欄・演算子選択・結果表示を用意する

まずは、電卓のUIとなるHTMLを用意します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 42 前半:簡易電卓</title>
  <style>
    /* 結果表示を少し目立たせるためのスタイル */
    #result {
      font-weight: bold;
      margin-top: 8px;
    }

    /* エラーメッセージ用のスタイル */
    .error {
      color: red;
      font-weight: bold;
    }
  </style>
</head>
<body>
  <h1>簡易電卓演習</h1>

  <!-- ▼ 数値Aの入力欄 -->
  <label for="numberA">数値A:</label>
  <input type="text" id="numberA" placeholder="例:10">

  <!-- ▼ 演算子の選択 -->
  <label for="operator">演算子:</label>
  <select id="operator">
    <option value="+">+(足し算)</option>
    <option value="-">−(引き算)</option>
    <option value="*">×(掛け算)</option>
    <option value="/">÷(割り算)</option>
  </select>

  <!-- ▼ 数値Bの入力欄 -->
  <label for="numberB">数値B:</label>
  <input type="text" id="numberB" placeholder="例:5">

  <!-- ▼ 計算ボタン -->
  <button id="calculateButton">計算する</button>

  <!-- ▼ 結果表示エリア -->
  <p id="result">結果:まだ計算していません。</p>

  <!-- ▼ エラーメッセージ表示エリア -->
  <p id="errorMessage"></p>

  <script>
    // ここにJavaScriptを書いていきます
  </script>
</body>
</html>

ここでのポイントは、

  • 数値入力欄を2つ用意していること
  • 演算子を <select> で選べるようにしていること
  • 結果表示用の <p id="result"> と、エラー表示用の <p id="errorMessage"> を分けていること

です。

JavaScriptでDOM要素を取得する

電卓に必要な要素を変数にまとめる

次に、JavaScriptで必要なDOM要素を取得します。

// ▼ 数値Aの入力欄
const numberAElement = document.getElementById('numberA');

// ▼ 数値Bの入力欄
const numberBElement = document.getElementById('numberB');

// ▼ 演算子のセレクトボックス
const operatorElement = document.getElementById('operator');

// ▼ 計算ボタン
const calculateButtonElement = document.getElementById('calculateButton');

// ▼ 結果表示用の要素
const resultElement = document.getElementById('result');

// ▼ エラーメッセージ表示用の要素
const errorMessageElement = document.getElementById('errorMessage');
JavaScript

DOM要素を変数にまとめておくことで、 後の処理が読みやすくなります。

数字入力を“数値として扱う”ことを理解する

入力欄の値は文字列として取得される

input 要素の値は、value プロパティから取得できますが、 そのままだと 文字列 として扱われます。

const valueA = numberAElement.value; // "10" のような文字列
const valueB = numberBElement.value; // "5" のような文字列
JavaScript

文字列のまま計算すると、 例えば "10" + "5""105" になってしまいます。

そこで、 数値に変換する処理 が必要になります。

Number() で文字列を数値に変換する

JavaScriptでは、Number() を使って文字列を数値に変換できます。

const valueA = numberAElement.value;
const valueB = numberBElement.value;

// ▼ 文字列を数値に変換します
const numberA = Number(valueA);
const numberB = Number(valueB);
JavaScript

ここでのポイントは、

  • Number("10")10(数値)になること
  • 数値に変換してから計算しないと、正しい四則演算にならないこと

です。

計算ボタンにイベントを設定する

clickイベントで「計算する」処理を呼び出す

電卓の中心となる処理は、 「計算する」ボタンがクリックされたときに実行されます。

calculateButtonElement.addEventListener('click', function () {
  // ▼ ここに計算処理を書いていきます
});
JavaScript

この中で、

  1. 入力値を取得する
  2. 数値に変換する
  3. 演算子を取得する
  4. 四則演算を行う
  5. 結果を表示する
  6. エラーがあればメッセージを表示する

という流れを作っていきます。

入力値を取得してバリデーションする

入力値を取得する

calculateButtonElement.addEventListener('click', function () {
  // ▼ 入力値(文字列)を取得します
  const valueA = numberAElement.value;
  const valueB = numberBElement.value;
  const operator = operatorElement.value;

  // ▼ まずはエラーメッセージをクリアします
  errorMessageElement.textContent = '';
  errorMessageElement.classList.remove('error');
});
JavaScript

ここで、 演算子は selectvalue から取得できます。

入力値が空でないかチェックする

初心者向けの電卓でも、 入力チェック(バリデーション) はとても大事です。

// ▼ 空入力のチェック
  if (valueA.trim() === '' || valueB.trim() === '') {
    errorMessageElement.textContent = '数値Aと数値Bの両方を入力してください。';
    errorMessageElement.classList.add('error');
    resultElement.textContent = '結果:入力エラーです。';
    return; // 処理をここで終了します
  }
JavaScript

ここでのポイントは、

  • trim() で前後の空白を取り除いてから空文字かどうかをチェックしていること
  • エラーがあった場合は return で処理を止めていること

です。

数値に変換して、数値かどうかをチェックする

次に、文字列を数値に変換し、 数値として扱えるかどうかを確認します。

// ▼ 文字列を数値に変換します
  const numberA = Number(valueA);
  const numberB = Number(valueB);

  // ▼ 数値として扱えるかどうかをチェックします
  if (Number.isNaN(numberA) || Number.isNaN(numberB)) {
    errorMessageElement.textContent = '数値Aと数値Bには数値を入力してください。';
    errorMessageElement.classList.add('error');
    resultElement.textContent = '結果:入力エラーです。';
    return;
  }
JavaScript

ここでのポイントは、

  • Number() で変換した結果が NaN(Not a Number)かどうかを Number.isNaN() でチェックしていること
  • 数値でない場合は、計算を行わずにエラーとして扱っていること

です。

四則演算を実装する

演算子に応じて計算方法を切り替える

演算子は +, -, *, / の4種類です。 これに応じて計算方法を切り替えます。

let result; // 計算結果を入れる変数

  if (operator === '+') {
    result = numberA + numberB;
  } else if (operator === '-') {
    result = numberA - numberB;
  } else if (operator === '*') {
    result = numberA * numberB;
  } else if (operator === '/') {
    // ▼ 割り算のときは、0で割っていないかチェックします
    if (numberB === 0) {
      errorMessageElement.textContent = '0で割ることはできません。';
      errorMessageElement.classList.add('error');
      resultElement.textContent = '結果:計算エラーです。';
      return;
    }
    result = numberA / numberB;
  } else {
    // ▼ 想定外の演算子が来た場合(通常は起こりません)
    errorMessageElement.textContent = '不正な演算子が指定されました。';
    errorMessageElement.classList.add('error');
    resultElement.textContent = '結果:計算エラーです。';
    return;
  }
JavaScript

ここでの重要ポイントは、

  • 演算子ごとに計算方法を分岐していること
  • 割り算のときに 0で割ることを禁止している こと
  • 想定外の演算子が来た場合にも、 エラーとして扱う安全な設計にしていること

です。

結果を画面に表示する

結果表示エリアにテキストとして反映する

計算結果を resultElement に表示します。

// ▼ 計算結果を表示します
  resultElement.textContent = `結果:${result}`;
JavaScript

ここで textContent を使っているのは、 ユーザー入力や計算結果を安全にテキストとして扱うためです。

innerHTML を使うと、 文字列がHTMLとして解釈されてしまい、 意図しないタグやスクリプトが実行される危険があります。

完成コード(コメント付き簡易電卓)

ここまでの内容を1つにまとめた完成コードです。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 42 前半:簡易電卓</title>
  <style>
    #result {
      font-weight: bold;
      margin-top: 8px;
    }

    .error {
      color: red;
      font-weight: bold;
    }
  </style>
</head>
<body>
  <h1>簡易電卓演習</h1>

  <label for="numberA">数値A:</label>
  <input type="text" id="numberA" placeholder="例:10">

  <label for="operator">演算子:</label>
  <select id="operator">
    <option value="+">+(足し算)</option>
    <option value="-">−(引き算)</option>
    <option value="*">×(掛け算)</option>
    <option value="/">÷(割り算)</option>
  </select>

  <label for="numberB">数値B:</label>
  <input type="text" id="numberB" placeholder="例:5">

  <button id="calculateButton">計算する</button>

  <p id="result">結果:まだ計算していません。</p>
  <p id="errorMessage"></p>

  <script>
    // ▼ DOM要素の取得
    const numberAElement = document.getElementById('numberA');
    const numberBElement = document.getElementById('numberB');
    const operatorElement = document.getElementById('operator');
    const calculateButtonElement = document.getElementById('calculateButton');
    const resultElement = document.getElementById('result');
    const errorMessageElement = document.getElementById('errorMessage');

    // ▼ 計算ボタンがクリックされたときの処理
    calculateButtonElement.addEventListener('click', function () {
      // 入力値(文字列)を取得します
      const valueA = numberAElement.value;
      const valueB = numberBElement.value;
      const operator = operatorElement.value;

      // エラーメッセージをクリアします
      errorMessageElement.textContent = '';
      errorMessageElement.classList.remove('error');

      // 空入力のチェック
      if (valueA.trim() === '' || valueB.trim() === '') {
        errorMessageElement.textContent = '数値Aと数値Bの両方を入力してください。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:入力エラーです。';
        return;
      }

      // 文字列を数値に変換します
      const numberA = Number(valueA);
      const numberB = Number(valueB);

      // 数値として扱えるかどうかをチェックします
      if (Number.isNaN(numberA) || Number.isNaN(numberB)) {
        errorMessageElement.textContent = '数値Aと数値Bには数値を入力してください。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:入力エラーです。';
        return;
      }

      let result;

      // 演算子に応じて計算方法を切り替えます
      if (operator === '+') {
        result = numberA + numberB;
      } else if (operator === '-') {
        result = numberA - numberB;
      } else if (operator === '*') {
        result = numberA * numberB;
      } else if (operator === '/') {
        // 0で割ることはできないのでチェックします
        if (numberB === 0) {
          errorMessageElement.textContent = '0で割ることはできません。';
          errorMessageElement.classList.add('error');
          resultElement.textContent = '結果:計算エラーです。';
          return;
        }
        result = numberA / numberB;
      } else {
        // 想定外の演算子(通常は起こりません)
        errorMessageElement.textContent = '不正な演算子が指定されました。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:計算エラーです。';
        return;
      }

      // 計算結果を表示します
      resultElement.textContent = `結果:${result}`;
    });
  </script>
</body>
</html>

少しだけ発展させる:小数点や桁数の扱い

簡易電卓をもう少し実用的にするなら、 次のような発展も考えられます。

  • 小数点を含む計算(例:10.5 + 3.2
  • 結果の小数点以下を丸める(例:小数点以下2桁まで表示)

例えば、結果を小数点以下2桁に丸めるには、 result.toFixed(2) を使うことができます。

resultElement.textContent = `結果:${result.toFixed(2)}`;
JavaScript

ただし、toFixed() は文字列を返すため、 後でさらに計算したい場合は注意が必要です。

セキュリティ・安全性の視点からの補足

電卓のようなシンプルなアプリでも、 次の点を意識しておくと、より安全で堅牢なコードになります。

  • ユーザー入力を画面に表示するときは、必ず textContent を使う
    • innerHTML を使うと、入力された文字列がHTMLとして解釈されてしまい、 <script> などが実行される危険があります。
  • 入力値のチェック(空・数値かどうか・0で割っていないかなど)を必ず行う
  • 想定外の状態(不正な演算子など)に対しても、 「何もしない」ではなく「エラーとして扱う」ようにしておく

こうした習慣は、 小さな電卓でも、大きなWebサービスでも同じように重要です。

Day 42 前半 練習用テンプレート

最後に、今日の内容をそのまま試せる練習用テンプレートを紹介します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 42 前半:簡易電卓 練習テンプレート</title>
  <style>
    #result {
      font-weight: bold;
      margin-top: 8px;
    }
    .error {
      color: red;
      font-weight: bold;
    }
  </style>
</head>
<body>
  <h1>簡易電卓 練習</h1>

  <input type="text" id="numberA" placeholder="数値A">
  <select id="operator">
    <option value="+">+</option>
    <option value="-">−</option>
    <option value="*">×</option>
    <option value="/">÷</option>
  </select>
  <input type="text" id="numberB" placeholder="数値B">
  <button id="calculateButton">計算する</button>

  <p id="result">結果:まだ計算していません。</p>
  <p id="errorMessage"></p>

  <script>
    console.log('--- 簡易電卓 練習開始 ---');

    const numberAElement = document.getElementById('numberA');
    const numberBElement = document.getElementById('numberB');
    const operatorElement = document.getElementById('operator');
    const calculateButtonElement = document.getElementById('calculateButton');
    const resultElement = document.getElementById('result');
    const errorMessageElement = document.getElementById('errorMessage');

    calculateButtonElement.addEventListener('click', () => {
      const valueA = numberAElement.value;
      const valueB = numberBElement.value;
      const operator = operatorElement.value;

      errorMessageElement.textContent = '';
      errorMessageElement.classList.remove('error');

      if (valueA.trim() === '' || valueB.trim() === '') {
        errorMessageElement.textContent = '両方の数値を入力してください。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:入力エラーです。';
        return;
      }

      const numberA = Number(valueA);
      const numberB = Number(valueB);

      if (Number.isNaN(numberA) || Number.isNaN(numberB)) {
        errorMessageElement.textContent = '数値を入力してください。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:入力エラーです。';
        return;
      }

      let result;

      if (operator === '+') {
        result = numberA + numberB;
      } else if (operator === '-') {
        result = numberA - numberB;
      } else if (operator === '*') {
        result = numberA * numberB;
      } else if (operator === '/') {
        if (numberB === 0) {
          errorMessageElement.textContent = '0で割ることはできません。';
          errorMessageElement.classList.add('error');
          resultElement.textContent = '結果:計算エラーです。';
          return;
        }
        result = numberA / numberB;
      } else {
        errorMessageElement.textContent = '不正な演算子です。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:計算エラーです。';
        return;
      }

      resultElement.textContent = `結果:${result}`;
      console.log('計算結果:', result);
    });

    console.log('--- 簡易電卓 練習テンプレートの準備が完了しました ---');
  </script>
</body>
</html>

Day 42 前半のまとめ

Day 42前半では、

  • 数字入力・演算子選択・結果表示という構成で、 シンプルな簡易電卓を作成したこと。
  • value から取得した文字列を Number() で数値に変換し、 四則演算を正しく行う流れを体験したこと。
  • 空入力・数値でない入力・0で割るケースなど、 バリデーションとエラーメッセージの設計を意識したこと。
  • textContent を使って安全に結果を表示する習慣を確認したこと。

を整理しました。

この簡易電卓は、 フォーム入力 → ロジック処理 → DOM反映という基本パターンの良い練習素材です。 後半では、さらに機能やUIを発展させていくことができます。


Day 42:DOM操作演習(後半)

「簡易電卓を“使いやすく・安全に”仕上げて、DOM+ロジック設計を深める」

Day 42後半では、前半で作成した簡易電卓をさらに発展させて、 「実際に使ってもストレスが少ない電卓」 を目指していきます。

テーマは同じく、

  • 数字入力
  • 四則演算
  • 結果表示

ですが、後半では次のようなポイントを意識して深掘りします。

  • 計算ロジックを関数に切り出して整理する
  • クリア機能(リセット)を追加する
  • エラー表示と正常表示を分かりやすく切り替える
  • セキュリティとユーザー体験を意識した設計にする

「とりあえず動く電卓」から、 「読める・直せる・拡張できる電卓」 に育てていきます。

電卓の“使い勝手”を考え直す

どんな機能があると、ユーザーは使いやすいか

前半の電卓は、次のような構成でした。

  • 数値A入力欄
  • 演算子選択欄
  • 数値B入力欄
  • 計算ボタン
  • 結果表示
  • エラーメッセージ表示

これでも十分動きますが、 実際に使うことを考えると、次のような機能があると便利です。

  • 入力を一度リセットする「クリア」ボタン
  • エラー時と正常時で結果表示の見た目を変える
  • 計算ロジックを関数にまとめて、コードを読みやすくする

後半では、こうした点を意識して設計していきます。

HTMLを“完成形”に近づける

クリアボタンと結果用のクラスを追加する

まずは、前半のHTMLに少しだけ要素を追加します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 42 後半:簡易電卓</title>
  <style>
    /* ▼ 結果表示を少し目立たせるためのスタイル */
    #result {
      font-weight: bold;
      margin-top: 8px;
    }

    /* ▼ エラーメッセージ用のスタイル */
    .error {
      color: red;
      font-weight: bold;
    }

    /* ▼ 正常な結果表示用のスタイル */
    .success {
      color: green;
      font-weight: bold;
    }
  </style>
</head>
<body>
  <h1>簡易電卓演習(後半)</h1>

  <!-- ▼ 数値Aの入力欄 -->
  <label for="numberA">数値A:</label>
  <input type="text" id="numberA" placeholder="例:10">

  <!-- ▼ 演算子の選択 -->
  <label for="operator">演算子:</label>
  <select id="operator">
    <option value="+">+(足し算)</option>
    <option value="-">−(引き算)</option>
    <option value="*">×(掛け算)</option>
    <option value="/">÷(割り算)</option>
  </select>

  <!-- ▼ 数値Bの入力欄 -->
  <label for="numberB">数値B:</label>
  <input type="text" id="numberB" placeholder="例:5">

  <!-- ▼ ボタンエリア -->
  <button id="calculateButton">計算する</button>
  <button id="clearButton">クリア</button>

  <!-- ▼ 結果表示エリア -->
  <p id="result">結果:まだ計算していません。</p>

  <!-- ▼ エラーメッセージ表示エリア -->
  <p id="errorMessage"></p>

  <script>
    // ここにJavaScriptを書いていきます
  </script>
</body>
</html>

追加したのは、

  • クリアボタン <button id="clearButton">
  • 結果表示用の .success クラス

です。

JavaScriptでDOM要素と“状態”を整理する

必要なDOM要素を取得する

// ▼ 数値Aの入力欄
const numberAElement = document.getElementById('numberA');

// ▼ 数値Bの入力欄
const numberBElement = document.getElementById('numberB');

// ▼ 演算子のセレクトボックス
const operatorElement = document.getElementById('operator');

// ▼ 計算ボタン
const calculateButtonElement = document.getElementById('calculateButton');

// ▼ クリアボタン
const clearButtonElement = document.getElementById('clearButton');

// ▼ 結果表示用の要素
const resultElement = document.getElementById('result');

// ▼ エラーメッセージ表示用の要素
const errorMessageElement = document.getElementById('errorMessage');
JavaScript

ここまでは前半と似ていますが、 後半では 「計算ロジックを関数に切り出す」 ことが重要になります。

計算ロジックを関数にまとめる

calculate() 関数で「入力 → バリデーション → 計算 → 結果表示」を一括管理する

電卓の中心となる処理を、 calculate() という関数にまとめます。

function calculate() {
  // ▼ 入力値(文字列)を取得します
  const valueA = numberAElement.value;
  const valueB = numberBElement.value;
  const operator = operatorElement.value;

  // ▼ 表示状態を初期化します
  errorMessageElement.textContent = '';
  errorMessageElement.classList.remove('error');
  resultElement.classList.remove('success');
  resultElement.classList.remove('error');

  // ▼ 空入力のチェック
  if (valueA.trim() === '' || valueB.trim() === '') {
    errorMessageElement.textContent = '数値Aと数値Bの両方を入力してください。';
    errorMessageElement.classList.add('error');
    resultElement.textContent = '結果:入力エラーです。';
    resultElement.classList.add('error');
    return;
  }

  // ▼ 文字列を数値に変換します
  const numberA = Number(valueA);
  const numberB = Number(valueB);

  // ▼ 数値として扱えるかどうかをチェックします
  if (Number.isNaN(numberA) || Number.isNaN(numberB)) {
    errorMessageElement.textContent = '数値Aと数値Bには数値を入力してください。';
    errorMessageElement.classList.add('error');
    resultElement.textContent = '結果:入力エラーです。';
    resultElement.classList.add('error');
    return;
  }

  let result;

  // ▼ 演算子に応じて計算方法を切り替えます
  if (operator === '+') {
    result = numberA + numberB;
  } else if (operator === '-') {
    result = numberA - numberB;
  } else if (operator === '*') {
    result = numberA * numberB;
  } else if (operator === '/') {
    // 割り算のときは、0で割っていないかチェックします
    if (numberB === 0) {
      errorMessageElement.textContent = '0で割ることはできません。';
      errorMessageElement.classList.add('error');
      resultElement.textContent = '結果:計算エラーです。';
      resultElement.classList.add('error');
      return;
    }
    result = numberA / numberB;
  } else {
    // 想定外の演算子(通常は起こりません)
    errorMessageElement.textContent = '不正な演算子が指定されました。';
    errorMessageElement.classList.add('error');
    resultElement.textContent = '結果:計算エラーです。';
    resultElement.classList.add('error');
    return;
  }

  // ▼ 正常な結果を表示します
  resultElement.textContent = `結果:${result}`;
  resultElement.classList.add('success');
}
JavaScript

ここでの重要ポイントは、

  • 入力チェック・数値変換・四則演算・結果表示を 1つの関数にまとめている こと
  • エラー時と正常時で、結果表示のクラスを切り替えていること
  • textContent を使って、ユーザー入力や結果を安全に表示していること

です。

イベントから calculate() を呼び出す

計算ボタンのクリックで calculate() を実行する

calculateButtonElement.addEventListener('click', function () {
  calculate();
});
JavaScript

これで、

  • ユーザーが「計算する」ボタンを押すたびに
  • calculate() が呼ばれ、
  • 入力 → バリデーション → 計算 → 結果表示

という流れが実行されます。

Enterキーでも計算できるようにする(発展)

少しだけ使い勝手を良くするために、 Enterキーで計算できるようにすることもできます。

numberBElement.addEventListener('keydown', function (event) {
  if (event.key === 'Enter') {
    calculate();
  }
});
JavaScript

ここでのポイントは、

  • keydown イベントで event.key を見ていること
  • 「最後の入力欄で Enter を押したら計算」という自然な操作を実現していること

です。

クリア機能(リセット)を追加する

clear() 関数で入力と表示を初期状態に戻す

電卓を使っていると、 「一度全部消してやり直したい」という場面がよくあります。

そこで、 clear() 関数を作って、入力と表示を初期状態に戻します。

function clearCalculator() {
  // ▼ 入力欄を空にします
  numberAElement.value = '';
  numberBElement.value = '';

  // ▼ 演算子を初期値(足し算)に戻します
  operatorElement.value = '+';

  // ▼ 結果表示を初期状態に戻します
  resultElement.textContent = '結果:まだ計算していません。';
  resultElement.classList.remove('success');
  resultElement.classList.remove('error');

  // ▼ エラーメッセージを消します
  errorMessageElement.textContent = '';
  errorMessageElement.classList.remove('error');
}
JavaScript

ここでのポイントは、

  • 入力欄・演算子・結果表示・エラーメッセージを すべて初期状態に戻している こと
  • 「初期状態の表示文言」を決めておくことで、 ユーザーが今の状態を理解しやすくなること

です。

クリアボタンにイベントを設定する

clearButtonElement.addEventListener('click', function () {
  clearCalculator();
});
JavaScript

これで、 ユーザーが「クリア」ボタンを押すと、 電卓全体がリセットされます。

完成コード(コメント付き・発展版簡易電卓)

ここまでの内容を1つにまとめた完成コードです。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 42 後半:簡易電卓</title>
  <style>
    #result {
      font-weight: bold;
      margin-top: 8px;
    }

    .error {
      color: red;
      font-weight: bold;
    }

    .success {
      color: green;
      font-weight: bold;
    }
  </style>
</head>
<body>
  <h1>簡易電卓演習(後半)</h1>

  <label for="numberA">数値A:</label>
  <input type="text" id="numberA" placeholder="例:10">

  <label for="operator">演算子:</label>
  <select id="operator">
    <option value="+">+(足し算)</option>
    <option value="-">−(引き算)</option>
    <option value="*">×(掛け算)</option>
    <option value="/">÷(割り算)</option>
  </select>

  <label for="numberB">数値B:</label>
  <input type="text" id="numberB" placeholder="例:5">

  <button id="calculateButton">計算する</button>
  <button id="clearButton">クリア</button>

  <p id="result">結果:まだ計算していません。</p>
  <p id="errorMessage"></p>

  <script>
    // ▼ DOM要素の取得
    const numberAElement = document.getElementById('numberA');
    const numberBElement = document.getElementById('numberB');
    const operatorElement = document.getElementById('operator');
    const calculateButtonElement = document.getElementById('calculateButton');
    const clearButtonElement = document.getElementById('clearButton');
    const resultElement = document.getElementById('result');
    const errorMessageElement = document.getElementById('errorMessage');

    // ▼ 計算処理をまとめた関数
    function calculate() {
      const valueA = numberAElement.value;
      const valueB = numberBElement.value;
      const operator = operatorElement.value;

      // 表示状態を初期化します
      errorMessageElement.textContent = '';
      errorMessageElement.classList.remove('error');
      resultElement.classList.remove('success');
      resultElement.classList.remove('error');

      // 空入力のチェック
      if (valueA.trim() === '' || valueB.trim() === '') {
        errorMessageElement.textContent = '数値Aと数値Bの両方を入力してください。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:入力エラーです。';
        resultElement.classList.add('error');
        return;
      }

      // 文字列を数値に変換します
      const numberA = Number(valueA);
      const numberB = Number(valueB);

      // 数値として扱えるかどうかをチェックします
      if (Number.isNaN(numberA) || Number.isNaN(numberB)) {
        errorMessageElement.textContent = '数値Aと数値Bには数値を入力してください。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:入力エラーです。';
        resultElement.classList.add('error');
        return;
      }

      let result;

      // 演算子に応じて計算方法を切り替えます
      if (operator === '+') {
        result = numberA + numberB;
      } else if (operator === '-') {
        result = numberA - numberB;
      } else if (operator === '*') {
        result = numberA * numberB;
      } else if (operator === '/') {
        if (numberB === 0) {
          errorMessageElement.textContent = '0で割ることはできません。';
          errorMessageElement.classList.add('error');
          resultElement.textContent = '結果:計算エラーです。';
          resultElement.classList.add('error');
          return;
        }
        result = numberA / numberB;
      } else {
        errorMessageElement.textContent = '不正な演算子が指定されました。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:計算エラーです。';
        resultElement.classList.add('error');
        return;
      }

      // 正常な結果を表示します
      resultElement.textContent = `結果:${result}`;
      resultElement.classList.add('success');
    }

    // ▼ クリア処理をまとめた関数
    function clearCalculator() {
      numberAElement.value = '';
      numberBElement.value = '';
      operatorElement.value = '+';

      resultElement.textContent = '結果:まだ計算していません。';
      resultElement.classList.remove('success');
      resultElement.classList.remove('error');

      errorMessageElement.textContent = '';
      errorMessageElement.classList.remove('error');
    }

    // ▼ 計算ボタンのイベント
    calculateButtonElement.addEventListener('click', function () {
      calculate();
    });

    // ▼ クリアボタンのイベント
    clearButtonElement.addEventListener('click', function () {
      clearCalculator();
    });

    // ▼ Enterキーで計算(発展)
    numberBElement.addEventListener('keydown', function (event) {
      if (event.key === 'Enter') {
        calculate();
      }
    });
  </script>
</body>
</html>

少しだけ発展させる:小数点と桁数の扱い

簡易電卓をもう少し実用的にするなら、 次のような発展も考えられます。

  • 小数点を含む計算(例:10.5 + 3.2
  • 結果の小数点以下を丸める(例:小数点以下2桁まで表示)

例えば、結果を小数点以下2桁に丸めるには、 result.toFixed(2) を使うことができます。

resultElement.textContent = `結果:${result.toFixed(2)}`;
JavaScript

ただし、toFixed() は文字列を返すため、 後でさらに計算したい場合は注意が必要です。

セキュリティ・ユーザー体験の視点からのまとめ

  • ユーザー入力や結果を画面に表示するときは、必ず textContent を使うことが重要です。
    • innerHTML を使うと、入力された文字列がHTMLとして解釈されてしまい、 <script> などが実行される危険があります。
  • 入力チェック(空・数値かどうか・0で割っていないかなど)を必ず行うことで、 想定外の動作やエラーを防ぐことができます。
  • エラー時と正常時で表示のスタイルを切り替えることで、 ユーザーは「今何が起きているか」を直感的に理解しやすくなります。

Day 42 後半 練習用テンプレート

最後に、今日の内容をそのまま試せる練習用テンプレートを紹介します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 42 後半:簡易電卓 練習テンプレート</title>
  <style>
    #result {
      font-weight: bold;
      margin-top: 8px;
    }
    .error {
      color: red;
      font-weight: bold;
    }
    .success {
      color: green;
      font-weight: bold;
    }
  </style>
</head>
<body>
  <h1>簡易電卓 総合練習</h1>

  <input type="text" id="numberA" placeholder="数値A">
  <select id="operator">
    <option value="+">+</option>
    <option value="-">−</option>
    <option value="*">×</option>
    <option value="/">÷</option>
  </select>
  <input type="text" id="numberB" placeholder="数値B">
  <button id="calculateButton">計算する</button>
  <button id="clearButton">クリア</button>

  <p id="result">結果:まだ計算していません。</p>
  <p id="errorMessage"></p>

  <script>
    console.log('--- 簡易電卓 総合練習開始 ---');

    const numberAElement = document.getElementById('numberA');
    const numberBElement = document.getElementById('numberB');
    const operatorElement = document.getElementById('operator');
    const calculateButtonElement = document.getElementById('calculateButton');
    const clearButtonElement = document.getElementById('clearButton');
    const resultElement = document.getElementById('result');
    const errorMessageElement = document.getElementById('errorMessage');

    function calculate() {
      const valueA = numberAElement.value;
      const valueB = numberBElement.value;
      const operator = operatorElement.value;

      errorMessageElement.textContent = '';
      errorMessageElement.classList.remove('error');
      resultElement.classList.remove('success');
      resultElement.classList.remove('error');

      if (valueA.trim() === '' || valueB.trim() === '') {
        errorMessageElement.textContent = '両方の数値を入力してください。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:入力エラーです。';
        resultElement.classList.add('error');
        return;
      }

      const numberA = Number(valueA);
      const numberB = Number(valueB);

      if (Number.isNaN(numberA) || Number.isNaN(numberB)) {
        errorMessageElement.textContent = '数値を入力してください。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:入力エラーです。';
        resultElement.classList.add('error');
        return;
      }

      let result;

      if (operator === '+') {
        result = numberA + numberB;
      } else if (operator === '-') {
        result = numberA - numberB;
      } else if (operator === '*') {
        result = numberA * numberB;
      } else if (operator === '/') {
        if (numberB === 0) {
          errorMessageElement.textContent = '0で割ることはできません。';
          errorMessageElement.classList.add('error');
          resultElement.textContent = '結果:計算エラーです。';
          resultElement.classList.add('error');
          return;
        }
        result = numberA / numberB;
      } else {
        errorMessageElement.textContent = '不正な演算子です。';
        errorMessageElement.classList.add('error');
        resultElement.textContent = '結果:計算エラーです。';
        resultElement.classList.add('error');
        return;
      }

      resultElement.textContent = `結果:${result}`;
      resultElement.classList.add('success');
      console.log('計算結果:', result);
    }

    function clearCalculator() {
      numberAElement.value = '';
      numberBElement.value = '';
      operatorElement.value = '+';
      resultElement.textContent = '結果:まだ計算していません。';
      resultElement.classList.remove('success');
      resultElement.classList.remove('error');
      errorMessageElement.textContent = '';
      errorMessageElement.classList.remove('error');
    }

    calculateButtonElement.addEventListener('click', calculate);
    clearButtonElement.addEventListener('click', clearCalculator);

    numberBElement.addEventListener('keydown', (event) => {
      if (event.key === 'Enter') {
        calculate();
      }
    });

    console.log('--- 簡易電卓 練習テンプレートの準備が完了しました ---');
  </script>
</body>
</html>

Day 42 後半のまとめ

Day 42後半では、

  • 簡易電卓を「入力 → バリデーション → 計算 → 結果表示」という流れで整理し、 calculate() 関数にまとめたこと。
  • クリア機能を追加して、入力と表示を初期状態に戻せるようにしたこと。
  • エラー時と正常時で表示スタイルを切り替え、 ユーザーにとって分かりやすいフィードバックを設計したこと。
  • セキュリティとユーザー体験の両方を意識しながら、 DOM操作とロジックを組み合わせる感覚を深めたこと。

を整理しました。

この電卓は、 フォーム入力 → ロジック処理 → DOM反映という基本パターンの良い総合演習になっています。

タイトルとURLをコピーしました