基礎から学ぶJavaScript入門 90日コース | JavaScriptでデータを扱う - Day 30:最初の総合制作

90日で身につけるJavaScript
スポンサーリンク
スポンサーリンク
  1. Day 29:自力コーディング練習(後半)
  2. 自力コーディングの基本方針
    1. ステップ1:紙やメモに“日本語で”手順を書く
    2. ステップ2:日本語の手順を“コードの骨組み”に変える
  3. 課題①:最大値を求める(自力コーディング用テンプレート)
    1. 思考ステップをコメントにしてから埋める
  4. 課題②:配列を検索(自力コーディング用テンプレート)
    1. 「最初に見つかった1件」を返す検索
  5. 課題③:データをフィルター(自力コーディング用テンプレート)
    1. 条件に合うものだけを新しい配列に集める
  6. 課題④:合計を計算(自力コーディング用テンプレート)
    1. 「蓄積」の基本パターンを体に染み込ませる
  7. 自力コーディング用ミニチェックリスト
    1. チェック1:関数の“入り口”と“出口”がはっきりしているか
    2. チェック2:ループの範囲が正しいか
    3. チェック3:条件式が意図通りか
    4. チェック4:元の配列を壊していないか
  8. 自力コーディング練習用テンプレート(ブラウザで実行しながら確認)
  9. Day 29 後半のまとめ
  10. Day 30:最初の総合制作(後半)
  11. 商品管理システムの土台設計
    1. 商品データの構造を決める
    2. 商品一覧を配列で管理する
  12. 商品一覧表示:すべての商品を見やすく出す
    1. 1件の商品を表示する関数
    2. 商品一覧を表示する関数
  13. 商品追加:新しい商品をシステムに登録する
    1. 追加前に簡単なチェックをする
    2. 商品追加関数を作る
  14. 商品検索:商品名で探す
    1. 部分一致で検索する関数
    2. 検索結果を表示する関数
  15. 価格フィルター:指定価格以下の商品だけを表示する
    1. フィルター関数を作る
    2. フィルター結果を表示する関数
  16. 合計金額計算:商品価格の合計を求める
    1. 合計関数を作る
    2. 合計金額を表示する関数
  17. 商品管理システム 総合テンプレート(ブラウザで実行可能)
  18. Day 30 後半のまとめ

Day 29:自力コーディング練習(後半)

「“見本なし”で書けるようになるための、実戦トレーニング」

Day 29後半では、前半で確認した

  • 最大値を求める
  • 配列を検索
  • データをフィルター
  • 合計を計算

という4つの課題を、本当に見本なしで書けるようになるための練習方法 を整理していきます。

ここでの主役は「コード」ではなく、 “どうやって自分の頭の中で組み立てるか” という思考プロセスです。

自力コーディングの基本方針

「いきなり書かない。まず“言葉”で組み立てる」

ステップ1:紙やメモに“日本語で”手順を書く

いきなりコードを書こうとすると、 文法やスペルに意識が取られて、肝心の「処理の流れ」がぼやけてしまいます。

そこで、まずは 日本語で手順を書く ことをおすすめします。

例:最大値を求める場合

  1. 配列が空なら「最大値なし」とする
  2. 最初の要素を「仮の最大値」とする
  3. 2番目以降の要素を順番に見ていく
  4. 今の値が仮の最大値より大きければ、仮の最大値を更新する
  5. 最後まで見終わったときの仮の最大値が答え

この「日本語の手順」が、 そのまま for文・if文・変数更新 に変換されていきます。

ステップ2:日本語の手順を“コードの骨組み”に変える

次に、その手順をコードの骨組みにします。

例:最大値の骨組み

function findMax(numbers) {
  // 1. 配列が空なら「最大値なし」
  // 2. 最初の要素を仮の最大値
  // 3. 2番目以降を順番に見る
  // 4. 大きければ更新
  // 5. 最後に仮の最大値を返す
}
JavaScript

このように、コメントだけ先に書いておく と、 「何を書くべきか」がはっきりした状態でコードを書けます。

課題①:最大値を求める(自力コーディング用テンプレート)

思考ステップをコメントにしてから埋める

// 数値配列の最大値を求める関数(自力コーディング練習用)
function findMax(numbers) {
  // 1. 配列が空かどうかをチェックする
  //    → 空ならnullを返す

  // 2. 最初の要素を「仮の最大値」として変数に入れる

  // 3. 2番目以降の要素をfor文で順番に見る

  // 4. 今の値が仮の最大値より大きければ、仮の最大値を更新する

  // 5. 最後に仮の最大値を返す
}
JavaScript

このテンプレートを使って、 コメントをヒントにしながら、自分で中身を埋める 練習をすると効果的です。

課題②:配列を検索(自力コーディング用テンプレート)

「最初に見つかった1件」を返す検索

// 配列から特定の値を検索する関数(自力コーディング練習用)
function findValueInArray(array, target) {
  // 1. 配列を先頭から順番にfor文で回す

  // 2. 各要素がtargetと一致するかどうかをif文で判定する

  // 3. 一致したら、その値をreturnで返す

  // 4. 最後まで見ても見つからなかった場合はnullを返す
}
JavaScript

ここでも、 「for → if → return → 最後にnull」 という流れを、 頭の中でなぞりながら書いていきます。

課題③:データをフィルター(自力コーディング用テンプレート)

条件に合うものだけを新しい配列に集める

// 数値配列から、指定した値以上のものだけを集める関数(自力コーディング練習用)
function filterGreaterOrEqual(numbers, threshold) {
  // 1. 結果を入れるための空の配列resultを用意する

  // 2. 元の配列numbersをfor文で先頭から順番に回す

  // 3. 各要素valueがthreshold以上かどうかをif文で判定する

  // 4. 条件に合う場合はresultにpushする

  // 5. ループが終わったらresultを返す
}
JavaScript

フィルターは、

  • 「空の配列を用意する」
  • 「条件に合うものだけpushする」

という2点をセットで覚えておくと、 どんな条件にも応用しやすくなります。

課題④:合計を計算(自力コーディング用テンプレート)

「蓄積」の基本パターンを体に染み込ませる

// 数値配列の合計を計算する関数(自力コーディング練習用)
function calculateSum(numbers) {
  // 1. 合計を入れる変数sumを0で初期化する

  // 2. 配列numbersをfor文で先頭から順番に回す

  // 3. 各要素valueをsumに足していく(sum += value)

  // 4. ループが終わったらsumを返す
}
JavaScript

この「sumを0からスタートして足し込んでいく」パターンは、 平均値・スコア集計・売上合計など、 あらゆる場面で使われる重要な型です。

自力コーディング用ミニチェックリスト

「書き終わったあとに、自分で見直すポイント」

チェック1:関数の“入り口”と“出口”がはっきりしているか

  • 引数は何を受け取る前提になっているか
  • 戻り値は何を返す前提になっているか
  • 「見つからない」「空配列」のときの扱いを決めているか

チェック2:ループの範囲が正しいか

  • for (let i = 0; i < array.length; i++)i の初期値と条件は正しいか
  • 1番目から回すのか、2番目から回すのかを意識できているか

チェック3:条件式が意図通りか

  • >=> を間違えていないか
  • ===== を意図して使っているか

チェック4:元の配列を壊していないか

  • フィルターや合計では、元の配列を書き換えていないか
  • 新しい配列や変数に結果を入れているか

自力コーディング練習用テンプレート(ブラウザで実行しながら確認)

最後に、 「自分で書いたコードを差し替えて試せる」ための シンプルなテンプレートを用意しておきます。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 29 後半:自力コーディング練習 用テンプレート</title>
</head>
<body>
  <h1>Day 29 後半:自力コーディング練習</h1>
  <p>ブラウザのコンソールを開いて、ログを確認してください。</p>

  <script>
    console.log('--- 自力コーディング練習開始 ---');

    // ここに自分で書いた関数を貼り付けて試していきます。
    // 例:findMax / findValueInArray / filterGreaterOrEqual / calculateSum など

    // サンプルデータ
    const numbers = [3, 10, 5, 8, 2];
    const numbers2 = [50, 120, 80, 200, 150];
    const numbers3 = [100, 200, 50];
    const fruits = ['apple', 'banana', 'orange'];

    // ここから下は、自分で書いた関数を呼び出してテストする場所です。
    // 例:
    // console.log('最大値:', findMax(numbers));
    // console.log('検索結果:', findValueInArray(fruits, 'banana'));
    // console.log('フィルター結果:', filterGreaterOrEqual(numbers2, 100));
    // console.log('合計:', calculateSum(numbers3));

    console.log('--- 自力コーディング練習テンプレートの実行が完了しました ---');
  </script>
</body>
</html>

このテンプレートの中に、 自分で書いた関数をコピペして動かしてみる ことで、

  • うまく動いたときの「できた!」という感覚
  • うまく動かなかったときの「どこが違うんだろう?」という気づき

を積み重ねていくことができます。

Day 29 後半のまとめ

Day 29後半では、

  • いきなりコードを書かず、まず「日本語で手順を書く」こと
  • コメントを“骨組み”として先に書き、そのあと中身を埋める練習方法
  • 最大値・検索・フィルター・合計という4つの課題を、 自力で書くためのテンプレートとチェックポイント

を整理しました。

自力コーディングは、 「悩む時間」そのものが成長の時間 です。

見本を閉じて、 少し不安なまま手を動かしてみる—— その一歩を何度も踏むことで、 「自分の書き方」「自分の癖」「自分の得意パターン」が 少しずつ育っていきます。

Day 30以降も、この「自力で組み立てる感覚」を軸にしながら、 より実践的なコードへ進んでいくことになりますので、 ぜひ今日の練習を何度か繰り返して、 自分の中に“書ける感覚”を定着させていってください。


Day 30:最初の総合制作(後半)

「小さな“商品管理システム”を完成させる」

Day 30後半では、これまで学んだ

  • 配列・オブジェクト
  • 検索・フィルター・ソート・合計
  • 関数による部品化

を総動員して、商品管理システム を1つの形にまとめていきます。 ここではコンソール上で動く「ミニ商品管理アプリ」を作りながら、

  • 商品追加
  • 商品一覧
  • 商品検索
  • 価格フィルター
  • 合計金額計算

を、1つの“まとまった仕組み”として組み立てていきます。

商品管理システムの土台設計

商品データの構造を決める

まずは「商品1件」をどのような形で表現するかを決めます。

// 1件の商品データの例
const product = {
  id: 1,              // 商品を一意に識別するID
  name: 'ノート',     // 商品名
  price: 100,         // 価格(数値)
};
JavaScript
  • id:商品を識別するための番号
  • name:商品名
  • price:価格(数値)

商品一覧を配列で管理する

複数の商品をまとめて管理するために、配列を使います。

// 商品一覧(商品管理システムの“データベース”的な役割)
const products = [
  { id: 1, name: 'ノート',       price: 100 },
  { id: 2, name: 'ボールペン',   price: 150 },
  { id: 3, name: '消しゴム',     price: 80 },
];
JavaScript

この products 配列が、 商品管理システムの「中心となるデータ」です。

商品一覧表示:すべての商品を見やすく出す

1件の商品を表示する関数

まずは、1件の商品を見やすく表示する関数を作ります。

// 1件の商品を表示する関数
function printProduct(product) {
  console.log(`ID: ${product.id}/商品名: ${product.name}/価格: ${product.price}円`);
}
JavaScript

商品一覧を表示する関数

次に、配列 products を受け取って、全件を表示する関数を作ります。

// 商品一覧を表示する関数
function printProductList(products) {
  console.log('--- 商品一覧 ---');

  for (const product of products) {
    printProduct(product); // 1件ずつ表示
  }

  console.log('--- 商品一覧ここまで ---');
}

// 実行例
printProductList(products);
JavaScript
  • この関数は、後で「検索結果」「価格フィルター結果」を表示するときにも再利用します。
  • 「一覧表示」は、どんな管理システムでも必ず登場する基本機能です。

商品追加:新しい商品をシステムに登録する

追加前に簡単なチェックをする

商品追加では、最低限次のようなチェックを意識します。

  • id が数値であること
  • name が空文字でないこと
  • price が0以上の数値であること
  • 同じ id の商品が既に存在しないこと
// 新しい商品が妥当かどうかをざっくりチェックする関数
function validateNewProduct(newProduct) {
  if (typeof newProduct.id !== 'number' || Number.isNaN(newProduct.id)) {
    return { valid: false, message: 'IDが不正です。数値を指定してください。' };
  }

  if (typeof newProduct.name !== 'string' || newProduct.name.trim() === '') {
    return { valid: false, message: '商品名が不正です。空でない文字列を指定してください。' };
  }

  if (typeof newProduct.price !== 'number' || Number.isNaN(newProduct.price) || newProduct.price < 0) {
    return { valid: false, message: '価格が不正です。0以上の数値を指定してください。' };
  }

  return { valid: true, message: 'OK' };
}
JavaScript

商品追加関数を作る

// 新しい商品を追加する関数(バリデーション付き)
function addProduct(products, newProduct) {
  // 妥当性チェック
  const result = validateNewProduct(newProduct);
  if (!result.valid) {
    console.log('商品追加に失敗しました:' + result.message);
    return false;
  }

  // IDの重複チェック
  const exists = products.some(product => product.id === newProduct.id);
  if (exists) {
    console.log('商品追加に失敗しました:同じIDの商品が既に存在します。');
    return false;
  }

  // 問題なければ追加
  products.push(newProduct);
  console.log('商品を追加しました:', newProduct);
  return true;
}

// 実行例
const newProduct = { id: 4, name: 'シャープペンシル', price: 300 };
addProduct(products, newProduct);
printProductList(products);
JavaScript
  • バリデーションと重複チェックを入れることで、「おかしな商品」が登録されるのを防ぎます。
  • 実務のシステムでも、このようなチェックは非常に重要です。

商品検索:商品名で探す

部分一致で検索する関数

商品検索では、商品名にキーワードが含まれているかどうかで判定します。

// 商品名にキーワードが含まれている商品を検索する関数
function searchProductsByName(products, keyword) {
  if (typeof keyword !== 'string') {
    return [];
  }

  const trimmed = keyword.trim();
  if (trimmed === '') {
    return [];
  }

  const lowerKeyword = trimmed.toLowerCase();
  const result = [];

  for (const product of products) {
    const lowerName = product.name.toLowerCase();

    if (lowerName.includes(lowerKeyword)) {
      result.push(product);
    }
  }

  return result;
}
JavaScript

検索結果を表示する関数

function printSearchResult(products, keyword) {
  console.log(`--- 商品検索(キーワード: "${keyword}") ---`);

  const result = searchProductsByName(products, keyword);

  if (result.length === 0) {
    console.log('該当する商品は見つかりませんでした。');
    console.log('キーワードを変えて再度お試しください。');
  } else {
    printProductList(result);
  }

  console.log('--- 商品検索ここまで ---');
}

// 実行例
printSearchResult(products, 'ペン');
printSearchResult(products, 'ノート');
printSearchResult(products, '鉛筆'); // ヒットなし
JavaScript
  • キーワードが空文字や不正な型の場合は、結果0件としています。
  • 大文字・小文字を区別しない検索にすることで、使い勝手がよくなります。

価格フィルター:指定価格以下の商品だけを表示する

フィルター関数を作る

// 指定価格以下の商品だけを抽出する関数
function filterProductsByMaxPrice(products, maxPrice) {
  if (typeof maxPrice !== 'number' || Number.isNaN(maxPrice) || maxPrice < 0) {
    return [];
  }

  const result = [];

  for (const product of products) {
    if (typeof product.price !== 'number' || Number.isNaN(product.price)) {
      // 価格情報が不正な商品はスキップ
      continue;
    }

    if (product.price <= maxPrice) {
      result.push(product);
    }
  }

  return result;
}
JavaScript

フィルター結果を表示する関数

function printFilteredByMaxPrice(products, maxPrice) {
  console.log(`--- ${maxPrice}円以下の商品 ---`);

  const result = filterProductsByMaxPrice(products, maxPrice);

  if (result.length === 0) {
    console.log('条件に合う商品は見つかりませんでした。');
    console.log('価格の条件やデータを確認してください。');
  } else {
    printProductList(result);
  }

  console.log('--- 指定価格以下の商品表示ここまで ---');
}

// 実行例
printFilteredByMaxPrice(products, 150);
printFilteredByMaxPrice(products, -100); // 不正値 → 0件
JavaScript
  • 「条件に合うものだけを新しい配列に集める」というフィルターの基本パターンを使っています。
  • 不正な価格や不正な入力値に対しても、安全に動作するようにしています。

合計金額計算:商品価格の合計を求める

合計関数を作る

// 商品配列の合計金額を計算する関数
function calculateTotalPrice(products) {
  let total = 0;

  for (const product of products) {
    if (typeof product.price !== 'number' || Number.isNaN(product.price)) {
      // 価格が不正な商品はスキップ
      continue;
    }

    total += product.price;
  }

  return total;
}
JavaScript

合計金額を表示する関数

function printTotalPrice(products, label = '対象商品') {
  const total = calculateTotalPrice(products);
  console.log(`${label}の合計金額は ${total} 円です。`);
}

// 実行例:全商品の合計
printTotalPrice(products, '全商品');

// 実行例:150円以下商品の合計
const filtered = filterProductsByMaxPrice(products, 150);
printTotalPrice(filtered, '150円以下の商品');
JavaScript
  • 合計は「蓄積」の基本パターンです。
  • フィルター結果にも同じ関数を使い回せるようにしている点が重要です。

商品管理システム 総合テンプレート(ブラウザで実行可能)

以下は、Day 30後半の内容を1つにまとめた「商品管理システム」のテンプレートです。 ブラウザで開き、コンソールを見ながら動きを確認できるようになっています。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Day 30 後半:商品管理システム 総合テンプレート</title>
</head>
<body>
  <h1>Day 30 後半:最初の総合制作 - 商品管理システム</h1>
  <p>ブラウザのコンソールを開いて、ログを確認してください。</p>

  <script>
    console.log('--- 商品管理システム開始 ---');

    // 商品データの配列(初期データ)
    const products = [
      { id: 1, name: 'ノート',       price: 100 },
      { id: 2, name: 'ボールペン',   price: 150 },
      { id: 3, name: '消しゴム',     price: 80 },
    ];

    // 1件の商品を表示する関数
    function printProduct(product) {
      console.log(`ID: ${product.id}/商品名: ${product.name}/価格: ${product.price}円`);
    }

    // 商品一覧を表示する関数
    function printProductList(products) {
      console.log('--- 商品一覧 ---');
      for (const product of products) {
        printProduct(product);
      }
      console.log('--- 商品一覧ここまで ---');
    }

    // 新しい商品が妥当かどうかをチェックする関数
    function validateNewProduct(newProduct) {
      if (typeof newProduct.id !== 'number' || Number.isNaN(newProduct.id)) {
        return { valid: false, message: 'IDが不正です。数値を指定してください。' };
      }

      if (typeof newProduct.name !== 'string' || newProduct.name.trim() === '') {
        return { valid: false, message: '商品名が不正です。空でない文字列を指定してください。' };
      }

      if (typeof newProduct.price !== 'number' || Number.isNaN(newProduct.price) || newProduct.price < 0) {
        return { valid: false, message: '価格が不正です。0以上の数値を指定してください。' };
      }

      return { valid: true, message: 'OK' };
    }

    // 商品追加関数
    function addProduct(products, newProduct) {
      const result = validateNewProduct(newProduct);
      if (!result.valid) {
        console.log('商品追加に失敗しました:' + result.message);
        return false;
      }

      const exists = products.some(product => product.id === newProduct.id);
      if (exists) {
        console.log('商品追加に失敗しました:同じIDの商品が既に存在します。');
        return false;
      }

      products.push(newProduct);
      console.log('商品を追加しました:', newProduct);
      return true;
    }

    // 商品検索関数
    function searchProductsByName(products, keyword) {
      if (typeof keyword !== 'string') {
        return [];
      }

      const trimmed = keyword.trim();
      if (trimmed === '') {
        return [];
      }

      const lowerKeyword = trimmed.toLowerCase();
      const result = [];

      for (const product of products) {
        const lowerName = product.name.toLowerCase();
        if (lowerName.includes(lowerKeyword)) {
          result.push(product);
        }
      }

      return result;
    }

    function printSearchResult(products, keyword) {
      console.log(`--- 商品検索(キーワード: "${keyword}") ---`);

      const result = searchProductsByName(products, keyword);

      if (result.length === 0) {
        console.log('該当する商品は見つかりませんでした。');
        console.log('キーワードを変えて再度お試しください。');
      } else {
        printProductList(result);
      }

      console.log('--- 商品検索ここまで ---');
    }

    // 価格フィルター関数
    function filterProductsByMaxPrice(products, maxPrice) {
      if (typeof maxPrice !== 'number' || Number.isNaN(maxPrice) || maxPrice < 0) {
        return [];
      }

      const result = [];

      for (const product of products) {
        if (typeof product.price !== 'number' || Number.isNaN(product.price)) {
          continue;
        }

        if (product.price <= maxPrice) {
          result.push(product);
        }
      }

      return result;
    }

    function printFilteredByMaxPrice(products, maxPrice) {
      console.log(`--- ${maxPrice}円以下の商品 ---`);

      const result = filterProductsByMaxPrice(products, maxPrice);

      if (result.length === 0) {
        console.log('条件に合う商品は見つかりませんでした。');
        console.log('価格の条件やデータを確認してください。');
      } else {
        printProductList(result);
      }

      console.log('--- 指定価格以下の商品表示ここまで ---');
    }

    // 合計金額計算関数
    function calculateTotalPrice(products) {
      let total = 0;

      for (const product of products) {
        if (typeof product.price !== 'number' || Number.isNaN(product.price)) {
          continue;
        }
        total += product.price;
      }

      return total;
    }

    function printTotalPrice(products, label = '対象商品') {
      const total = calculateTotalPrice(products);
      console.log(`${label}の合計金額は ${total} 円です。`);
    }

    // --- 動作確認 ---

    console.log('初期状態の商品一覧:');
    printProductList(products);

    console.log('商品を追加します:');
    const newProduct = { id: 4, name: 'シャープペンシル', price: 300 };
    addProduct(products, newProduct);
    printProductList(products);

    console.log('商品検索のテスト:');
    printSearchResult(products, 'ペン');
    printSearchResult(products, 'ノート');
    printSearchResult(products, '鉛筆');

    console.log('価格フィルターのテスト:');
    printFilteredByMaxPrice(products, 150);
    printFilteredByMaxPrice(products, -100);

    console.log('合計金額計算のテスト:');
    printTotalPrice(products, '全商品');

    const filtered = filterProductsByMaxPrice(products, 150);
    printTotalPrice(filtered, '150円以下の商品');

    console.log('--- 商品管理システムの動作確認が完了しました ---');
  </script>
</body>
</html>

Day 30 後半のまとめ

Day 30後半では、

  • 商品追加・一覧・検索・価格フィルター・合計金額計算を 1つの「商品管理システム」としてまとめたこと
  • バリデーションや重複チェックを入れることで、 データの信頼性を守る感覚を持ったこと
  • 同じ表示関数・合計関数を、 検索結果やフィルター結果にも再利用する「部品化」の考え方を確認したこと

を整理しました。

ここまで来ると、 「小さくても、ちゃんと役に立つアプリ」を自分の手で作れる状態 に近づいています。

この商品管理システムは、 ユーザー管理・タスク管理・在庫管理など、 さまざまな分野に応用できる“型”になっていますので、 ぜひ自分なりに項目を増やしたり、 画面を付けてみたりしながら、 「自分のプロダクト」として育てていってください。

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