基礎から学ぶJavaScript入門 90日コース | ブラウザデータ保存 - Day 53:ソート機能

JavaScript 90日で身につけるJavaScript
スポンサーリンク
スポンサーリンク

Day 53:ソート機能

Day 53では、第4フェーズ「ブラウザデータ保存」の学習をさらに発展させて、ToDoアプリにソート機能を追加します。今回の実践テーマは、名前順、日付順、優先順位順の3つです。ここまでの学習では、localStorage を使った保存、ページ再読み込み対応、完了状態保存、検索機能、フィルター機能を学んできました。つまり、ToDoデータを配列で持ち、それを条件で絞り込んだり、状態ごとに表示を切り替えたりする考え方はすでに身についてきています。Day 53ではその続きとして、「どの順番で見せるか」をコントロールする方法を学びます。

検索やフィルターが「どれを表示するか」を決める機能だったのに対して、ソートは「表示する順番をどうするか」を決める機能です。この違いはとても重要です。たとえば、すべてのToDoを表示するという点では同じでも、名前順で並べるのか、新しい日付順で並べるのか、優先順位が高いものから並べるのかによって、使いやすさは大きく変わります。つまり、ソート機能は一覧の見やすさと操作しやすさを高めるための大切な機能です。

初心者の方にとって、今回の sort() は少し難しそうに見えるかもしれません。しかし、考え方を小さく分ければ十分理解できます。大切なのは、「何を基準に順番を決めるのか」をはっきりさせることです。名前順なら文字列、日付順なら日付データ、優先順位順なら数値やルールを使って比較します。今回も、用語だけを覚えるのではなく、どんな考え方で並べ替えが行われるのかを、初心者向けに段階的に整理していきます。

ソート機能とは何か

ソート機能とは、配列の中に入っているデータの順番を並べ替える機能です。たとえば、あいうえお順に並べたり、新しい順に並べたり、優先度が高いものを先に持ってきたりすることがソートです。

初心者の方は、ソートを次のように考えるとわかりやすいです。

  • 検索は「どれを表示するか」を決める
  • フィルターは「どんな条件のものを表示するか」を決める
  • ソートは「どんな順番で表示するか」を決める

つまり、ソートは「表示対象」ではなく「並び順」を変える機能です。この区別を最初にはっきりさせておくと、Day 53の内容が整理しやすくなります。

Day 53で特に大切な考え方

今回一番大切なのは、「同じデータでも、順番を変えるだけで見やすさや使いやすさが変わる」ということです。ToDoアプリにたくさんの項目が入ってくると、ただ追加順に並んでいるだけでは使いにくくなることがあります。たとえば、急ぎのToDoを先に見たい場合もあれば、期限が近いものから見たい場合もあります。あるいは、一覧を整理するために名前順で見たいこともあります。

つまり、ソート機能は「データを変える機能」ではなく、「データの並び方を変える機能」です。初心者の方は、ここでフィルター機能との違いをしっかり意識すると理解しやすいです。

ソートのために必要なデータ設計

Day 52までのToDoデータは、主に次のような形でした。

const todo = {
  text: "JavaScriptを勉強する",
  completed: false
};
JavaScript

しかし、今回のソート機能では、名前順だけでなく、日付順や優先順位順も扱いたいので、ToDoデータにもう少し情報が必要になります。たとえば、次のようにします。

const todo = {
  text: "JavaScriptを勉強する",
  completed: false,
  date: "2026-10-29",
  priority: 2
};
JavaScript

ここで、

  • `text` はToDo名です。
  • `completed` は完了状態です。
  • `date` は作成日や期限日として使う日付です。
  • `priority` は優先順位です。

初心者の方は、「ソートしたい項目があるなら、その情報を最初からデータに持たせる必要がある」と理解するとよいです。

sort() とは何か

JavaScriptでは、配列を並べ替えるときに sort() を使います。まずはシンプルな例を見てみます。

const numbers = [3, 1, 4, 2];

// 小さい順に並べ替える
numbers.sort(function (a, b) {
  return a - b;
});

console.log(numbers);
JavaScript

この結果、numbers は [1, 2, 3, 4] になります。

ここで初心者の方が最初に戸惑いやすいのは、function (a, b) と return a - b の部分です。これは、「aとbを比べて、どちらを前にするかを決めるルール」と考えるとわかりやすいです。

  • 負の値なら a を前にする
  • 正の値なら b を前にする
  • 0なら順番を変えない

このルールに基づいて、sort() は全体を並べ替えていきます。

sort() は元の配列を並べ替えることに注意する

ここは非常に重要なので深掘りします。filter() は新しい配列を作りますが、sort() は元の配列そのものを並べ替えます。つまり、todos.sort(...) と書くと、todos 配列の中身の順番が直接変わります。

これは便利でもありますが、初心者の方は注意が必要です。なぜなら、「見せ方だけ変えたい」のに、元データの順番まで変えてしまうことがあるからです。元データを残したい場合は、コピーを作ってからソートするのが安全です。

// 配列をコピーしてから並べ替える
const sortedTodos = [...todos].sort(function (a, b) {
  return a.text.localeCompare(b.text, "ja");
});
JavaScript

このようにすると、元の todos はそのままで、並べ替えた結果だけを別の配列として持てます。初心者の方は、sort() のこの性質を必ず押さえておきたいです。

名前順の考え方

まずは名前順です。ToDo名は文字列なので、文字列同士を比べる必要があります。日本語の文字列比較では、localeCompare() を使うとわかりやすいです。

const todos = [
  { text: "掃除", completed: false, date: "2026-10-29", priority: 2 },
  { text: "買い物", completed: false, date: "2026-10-27", priority: 1 },
  { text: "勉強", completed: true, date: "2026-10-28", priority: 3 }
];

// 名前順に並べ替える
const sortedByName = [...todos].sort(function (a, b) {
  return a.text.localeCompare(b.text, "ja");
});
JavaScript

このコードでは、text を基準に日本語として比較しています。初心者の方は、「名前順では数値の引き算ではなく、文字列の比較が必要」と覚えるとよいです。

名前順をかみ砕いて理解する

名前順ソートでは、「どちらの文字列が先に来るべきか」を1件ずつ比べています。localeCompare() は、その比較をわかりやすくしてくれる道具です。たとえば、「買い物」と「掃除」を比べて、どちらを先にするかを判断しています。

初心者の方にとって大切なのは、文字列は数字のように引き算できないという点です。そのため、文字列専用の比較方法を使う必要があります。ここを理解すると、名前順ソートの考え方がかなりすっきりします。

日付順の考え方

次は日付順です。日付順では、どの日付が新しいか古いかを比べる必要があります。文字列のままでも YYYY-MM-DD 形式なら比較しやすい場合がありますが、初心者向けには Date オブジェクトに変換して比較するほうが考え方がはっきりします。

// 日付順に並べ替える
const sortedByDate = [...todos].sort(function (a, b) {
  return new Date(a.date) - new Date(b.date);
});
JavaScript

このコードでは、日付の古い順に並びます。新しい順にしたい場合は逆にします。

// 新しい日付順に並べ替える
const sortedByDateDesc = [...todos].sort(function (a, b) {
  return new Date(b.date) - new Date(a.date);
});
JavaScript

初心者の方は、「日付も比較できる値に変えてから並べる」と考えると理解しやすいです。

日付順で注意したいこと

日付順では、日付データの形式がそろっていることがとても大切です。たとえば、2026-10-29 と 2026/10/29 が混ざっていたり、入力形式がばらばらだったりすると、思わぬ結果になることがあります。初心者の段階では、日付形式を統一しておくことがとても大事です。

また、作成日を自動で入れるのか、期限日を手入力するのかによって設計も変わります。今回は学習用として、まず YYYY-MM-DD の形で持つとわかりやすいです。

優先順位順の考え方

次は優先順位順です。優先順位は、たとえば数値で持つと扱いやすいです。

  • 1 = 高い
  • 2 = 普通
  • 3 = 低い

このように決めておけば、数値比較で並べ替えられます。

// 優先順位順に並べ替える
const sortedByPriority = [...todos].sort(function (a, b) {
  return a.priority - b.priority;
});
JavaScript

この場合、1 が最優先なので、1 → 2 → 3 の順に並びます。

初心者の方は、優先順位を文字列の「高・中・低」で持つよりも、まず数値で持つと比較しやすいと理解するとよいです。

優先順位順を見やすくする工夫

優先順位を数値で保存するのは比較しやすいですが、そのまま画面に 1 や 2 を出すと少しわかりにくいことがあります。そのため、表示するときは 高、中、低 に変換して見せる工夫があると実用的です。

たとえば、次のような関数を使えます。

// 優先順位の数字を文字に変える関数
function getPriorityLabel(priority) {
  if (priority === 1) {
    return "高";
  } else if (priority === 2) {
    return "中";
  } else {
    return "低";
  }
}
JavaScript

初心者の方は、「保存しやすい形」と「見せやすい形」は必ずしも同じではない、と理解しておくと設計の感覚が育ちやすいです。

まずは小さなソート例をまとめて見る

ここまでの3種類をまとめて見ると、次のようになります。

const todos = [
  { text: "掃除", completed: false, date: "2026-10-29", priority: 2 },
  { text: "買い物", completed: false, date: "2026-10-27", priority: 1 },
  { text: "勉強", completed: true, date: "2026-10-28", priority: 3 }
];

// 名前順
const sortedByName = [...todos].sort(function (a, b) {
  return a.text.localeCompare(b.text, "ja");
});

// 日付順
const sortedByDate = [...todos].sort(function (a, b) {
  return new Date(a.date) - new Date(b.date);
});

// 優先順位順
const sortedByPriority = [...todos].sort(function (a, b) {
  return a.priority - b.priority;
});
JavaScript

初心者の方は、「比較する対象が何か」に注目すると整理しやすいです。

  • 名前順は文字列比較です。
  • 日付順は日付比較です。
  • 優先順位順は数値比較です。

ソート機能付きToDoアプリのUIを考える

実際にアプリへ組み込むなら、ユーザーが並び順を選べるUIが必要です。今回は、わかりやすくボタンを使う形にします。

  • 名前順ボタン
  • 日付順ボタン
  • 優先順位順ボタン

この形なら、初心者の方にも「どのボタンがどの並び替えか」がわかりやすいです。

最初に必要なHTMLを考える

では、ソート機能付きToDoアプリのためのHTMLを用意します。

<h2>ToDoソートアプリ</h2>

<input type="text" id="todoInput" placeholder="ToDoを入力してください">
<input type="date" id="dateInput">
<select id="priorityInput">
  <option value="1">高</option>
  <option value="2">中</option>
  <option value="3">低</option>
</select>
<button id="addButton">追加</button>

<br><br>

<button id="nameSortButton">名前順</button>
<button id="dateSortButton">日付順</button>
<button id="prioritySortButton">優先順位順</button>

<ul id="todoList"></ul>

このHTMLでは、ToDo追加時に名前、日付、優先順位を入力できるようにしています。初心者の方は、「ソートしたいなら、そのための情報を入力できる必要がある」と理解しておくとよいです。

表示関数を整える

ソート結果を表示するため、表示関数は渡された配列を表示する形にします。

// ToDo を画面に表示する関数
function renderTodos(list) {
  todoList.innerHTML = "";

  list.forEach(function (todo) {
    const li = document.createElement("li");
    li.textContent = `${todo.text} | 日付: ${todo.date} | 優先順位: ${getPriorityLabel(todo.priority)}`;
    todoList.appendChild(li);
  });
}
JavaScript

これで、並び替えた配列をそのまま表示できます。

完成版テンプレート

ここでは、Day 53の基本をまとめた完成版テンプレートを載せます。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Day 53 ソート機能</title>
</head>
<body>
  <h2>ToDoソートアプリ</h2>

  <input type="text" id="todoInput" placeholder="ToDoを入力してください">
  <input type="date" id="dateInput">
  <select id="priorityInput">
    <option value="1">高</option>
    <option value="2">中</option>
    <option value="3">低</option>
  </select>
  <button id="addButton">追加</button>

  <br><br>

  <button id="nameSortButton">名前順</button>
  <button id="dateSortButton">日付順</button>
  <button id="prioritySortButton">優先順位順</button>
  <button id="showAllButton">追加順に戻す</button>

  <ul id="todoList"></ul>

  <script>
    // 必要な要素を取得する
    const todoInput = document.getElementById("todoInput");
    const dateInput = document.getElementById("dateInput");
    const priorityInput = document.getElementById("priorityInput");
    const addButton = document.getElementById("addButton");
    const nameSortButton = document.getElementById("nameSortButton");
    const dateSortButton = document.getElementById("dateSortButton");
    const prioritySortButton = document.getElementById("prioritySortButton");
    const showAllButton = document.getElementById("showAllButton");
    const todoList = document.getElementById("todoList");

    // ToDo データを入れる配列
    let todos = [];

    // 優先順位の数値を表示用の文字に変える関数
    function getPriorityLabel(priority) {
      if (priority === 1) {
        return "高";
      } else if (priority === 2) {
        return "中";
      } else {
        return "低";
      }
    }

    // ToDo を画面に表示する関数
    function renderTodos(list) {
      // 表示を空にする
      todoList.innerHTML = "";

      // 配列の内容を順番に表示する
      list.forEach(function (todo) {
        const li = document.createElement("li");
        li.textContent = `${todo.text} | 日付: ${todo.date} | 優先順位: ${getPriorityLabel(todo.priority)}`;
        todoList.appendChild(li);
      });
    }

    // 追加ボタンの処理
    addButton.addEventListener("click", function () {
      // 入力値を取得する
      const text = todoInput.value.trim();
      const date = dateInput.value;
      const priority = Number(priorityInput.value);

      // ToDo 名か日付が空なら追加しない
      if (text === "" || date === "") {
        return;
      }

      // ToDo を配列に追加する
      todos.push({
        text: text,
        completed: false,
        date: date,
        priority: priority
      });

      // 全件表示する
      renderTodos(todos);

      // 入力欄を空にする
      todoInput.value = "";
      dateInput.value = "";
      priorityInput.value = "1";
    });

    // 名前順ソート
    nameSortButton.addEventListener("click", function () {
      const sortedTodos = [...todos].sort(function (a, b) {
        return a.text.localeCompare(b.text, "ja");
      });

      renderTodos(sortedTodos);
    });

    // 日付順ソート
    dateSortButton.addEventListener("click", function () {
      const sortedTodos = [...todos].sort(function (a, b) {
        return new Date(a.date) - new Date(b.date);
      });

      renderTodos(sortedTodos);
    });

    // 優先順位順ソート
    prioritySortButton.addEventListener("click", function () {
      const sortedTodos = [...todos].sort(function (a, b) {
        return a.priority - b.priority;
      });

      renderTodos(sortedTodos);
    });

    // 追加順に戻す
    showAllButton.addEventListener("click", function () {
      renderTodos(todos);
    });

    // 最初は空の状態を表示する
    renderTodos(todos);
  </script>
</body>
</html>

この完成版で特に注目したいこと

初心者の方は、完成版コードを見るときに、次の点に注目すると理解しやすいです。

  • 追加時に名前、日付、優先順位を1件のオブジェクトとして保存していること
  • ソート時に元の `todos` を直接並べ替えず、`[…todos]` でコピーしていること
  • 比較対象が種類ごとに違うこと
  • 表示関数には「どの順に並んだ配列を見せるか」だけを渡していること

これらを意識すると、ソート機能が単なる魔法のコードではなく、データの性質に応じた比較処理だと理解しやすくなります。

初心者が特に注意したいポイント

Day 53では、次の点を特に意識すると理解が深まりやすいです。

  • `sort()` は元の配列を直接並べ替える性質があります。
  • 元データを残したいときは `[…]` でコピーしてから使うと安全です。
  • 名前順は文字列比較、日付順は日付比較、優先順位順は数値比較です。
  • ソートは表示対象を変えるのではなく、表示順を変える機能です。
  • ソートしたい基準の情報は、最初からデータに含めておく必要があります。

特に重要なのは、フィルターとソートを混同しないことです。フィルターは数を減らすことがありますが、ソートは数を減らさず順番だけを変えます。この違いがわかると、配列操作の理解がかなり整理しやすくなります。

情報セキュリティの観点での注意

今回のソート機能自体は主に表示順の制御ですが、日付や優先順位のような情報も保存対象になる場合があります。ToDoに扱う内容によっては、予定や行動パターンがわかることもあります。そのため、ブラウザ内に保存するToDo内容は、引き続き機密性の高い業務情報や秘密情報を避けるのが安全です。

初心者の方は、機能が増えるほど「何を保存しているのか」「それは保存してもよい内容か」を意識すると、安全なアプリ設計の感覚が育ちます。

Day 53のゴールを整理する

Day 53では、次のことができるようになっていれば十分です。

  • ソート機能の役割を説明できる
  • 検索・フィルター・ソートの違いを説明できる
  • `sort()` の基本的な使い方を理解している
  • 名前順、日付順、優先順位順で並べ替えができる
  • 元配列を守るためにコピーしてソートする考え方を説明できる
  • ソート基準に必要なデータを設計できる

ここまでできれば、Day 53としてはとても順調です。ToDoアプリの一覧表示を、より実用的で見やすい形に整える力がついてきています。

まとめ

Day 53では、第4フェーズ「ブラウザデータ保存」の発展として、ToDoアプリにソート機能を追加しました。今回学んだのは、名前順、日付順、優先順位順の3種類であり、それぞれ文字列、日付、数値という異なるデータ型を比較して並べ替える考え方でした。sort() は配列の順番を変えるためのメソッドですが、元の配列そのものを並べ替える性質があるため、元データを残したい場合は [...] でコピーしてからソートすることが重要です。

特に大切なのは、検索やフィルターとの違いを明確にすることです。検索やフィルターは「どれを表示するか」を決める機能であり、ソートは「どの順番で表示するか」を決める機能です。この違いが理解できると、一覧データを扱うアプリの設計がかなり整理しやすくなります。

次に進む前に、今回のテンプレートを何も見ずにもう一度作り直してみるのがおすすめです。そのうえで、フィルター機能や検索機能と組み合わせて、「未完了だけを優先順位順に並べる」といった応用に挑戦してみると、配列操作と表示制御の理解がさらに深まりやすくなります。

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