JavaScript Tips | 基本・共通ユーティリティ:汎用 – 連番生成

JavaScript JavaScript
スポンサーリンク

「連番生成」ユーティリティは何に使うのか

連番生成は、「1, 2, 3, 4, … と増えていく番号を、安全に・簡単に振るための仕組み」です。
業務コードでは、次のような場面でよく使います。

テーブルの行 ID(画面内だけで一意ならよい)
一時オブジェクトの識別子
ログの通し番号
「何番目の処理か」を分かるようにするためのカウンタ

毎回「どこかに let counter = 0 と書いて counter++ する」のもアリですが、
きちんとユーティリティとして切り出しておくと、
「どこで何の連番を振っているか」が分かりやすくなり、バグも減ります。


一番シンプルな連番生成:ただのカウンタ変数

まずは一番素朴な形から見てみます。

let counter = 0;

function nextId() {
  counter += 1;
  return counter;
}

console.log(nextId()); // 1
console.log(nextId()); // 2
console.log(nextId()); // 3
JavaScript

この nextId は呼ばれるたびに 1, 2, 3… と増えていきます。
仕組み自体はとても簡単です。

ただし、この形には弱点があります。
counter がグローバルに露出しているので、
他のコードから勝手に書き換えられてしまう可能性があります。

counter = 9999; // 誰かがこう書いたら、次の ID が 10000 から始まってしまう
JavaScript

業務コードでは、こういう「勝手に触られて壊れる状態」はできるだけ減らしたいので、
次のステップとして「カウンタを閉じ込める」形に進みます。


クロージャを使った「安全な連番生成器」

連番生成の定番パターンは、「カウンタを関数の中に閉じ込める」ことです。
これにはクロージャを使います。

function createSequence(start = 1) {
  let current = start - 1;

  return function next() {
    current += 1;
    return current;
  };
}
JavaScript

この createSequence は、「連番を生み出す関数」を作る工場のようなものです。
使い方を見てみましょう。

const nextRowId = createSequence(1);

console.log(nextRowId()); // 1
console.log(nextRowId()); // 2
console.log(nextRowId()); // 3
JavaScript

ここでの重要ポイントを丁寧に整理します。

createSequence が呼ばれたときに、current という変数が一つだけ作られる
next 関数は、その current を覚えたまま返される(これがクロージャ)
next を呼ぶたびに current が 1 ずつ増えて、その値が返る
currentcreateSequence の外からは直接触れない

つまり、「連番の状態(current)を外から隠しつつ、番号だけを取り出せる」仕組みになっています。
これが、業務で使える「安全な連番生成」の基本形です。


複数種類の連番を独立して持つ

クロージャを使うと、「用途ごとに別々の連番」を簡単に持てます。

const nextUserId = createSequence(1);
const nextOrderId = createSequence(1000);

console.log(nextUserId());  // 1
console.log(nextUserId());  // 2

console.log(nextOrderId()); // 1000
console.log(nextOrderId()); // 1001
JavaScript

nextUserIdnextOrderId は、それぞれ別の current を持っています。
ユーザー ID と注文 ID のカウンタが混ざることはありません。

ここでの深掘りポイントは、
「createSequence を呼ぶたびに“独立したカウンタ”が生まれる」という感覚です。
これを理解すると、「画面ごと」「機能ごと」に連番を分ける設計が自然にできるようになります。


連番にプレフィックスを付けて「意味のある ID」にする

単なる数字だけだと、ログやデバッグ時に「この 3 って何の 3?」となりがちです。
そこで、文字列のプレフィックスを付けておくと、用途が分かりやすくなります。

function createIdSequence(prefix = "id", start = 1) {
  const next = createSequence(start);

  return function nextId() {
    const n = next();
    return `${prefix}_${n}`;
  };
}
JavaScript

使い方はこうです。

const nextTempId = createIdSequence("temp", 1);
const nextRowId = createIdSequence("row", 1);

console.log(nextTempId()); // "temp_1"
console.log(nextTempId()); // "temp_2"

console.log(nextRowId());  // "row_1"
console.log(nextRowId());  // "row_2"
JavaScript

これで、ID を見ただけで「これは一時 ID」「これは行 ID」と分かるようになります。
業務ログやデバッグでの読みやすさが一気に上がります。


実務での具体的な利用イメージ

画面内の「仮 ID」としての連番

例えば、まだサーバーに保存していない行データに ID を振りたいとき。

const nextRowId = createIdSequence("row");

const rows = [];

rows.push({ id: nextRowId(), name: "行1" });
rows.push({ id: nextRowId(), name: "行2" });

console.log(rows);
// [
//   { id: "row_1", name: "行1" },
//   { id: "row_2", name: "行2" },
// ]
JavaScript

サーバーから本物の ID が返ってきたら、この仮 ID と紐づけて置き換える、というパターンがよくあります。

ログの通し番号としての連番

ログを見やすくするために、「この処理の中で何番目のステップか」を連番で出すこともできます。

const nextStepNo = createSequence(1);

function logStep(message) {
  const no = nextStepNo();
  console.log(`[STEP ${no}] ${message}`);
}

logStep("開始");
logStep("API 呼び出し");
logStep("結果をパース");
logStep("完了");
JavaScript

ログはこうなります。

[STEP 1] 開始
[STEP 2] API 呼び出し
[STEP 3] 結果をパース
[STEP 4] 完了

これだけで、「どの順番で何が起きたか」がかなり追いやすくなります。


連番生成で気をつけたいポイント

一つだけ意識しておいてほしいのは、
「連番は“そのプロセスの中だけで一意”という前提で使う」ということです。

ブラウザをリロードしたらカウンタはリセットされます。
サーバーのプロセスが再起動したら、また 1 から始まります。

なので、

画面内の一時 ID
一つの処理フローの中での通し番号

のような「ローカルな一意性」には連番が向いていますが、

システム全体で絶対にかぶってはいけない ID
複数サーバー間で共有する主キー

のような用途には、UUID やランダム ID の方が適しています。

この「連番の守備範囲」を理解しておくと、
どこで連番を使い、どこで UUID を使うべきかの判断がしやすくなります。


小さな練習で感覚をつかむ

最後に、次のようなことを自分で試してみてください。

createSequence を使って、
「ユーザー用」「注文用」「ログ用」の 3 種類の連番を作る
それぞれを何回か呼んで、番号が混ざらずに増えていくことを確認する

そのうえで、createIdSequence を使って
user_1, user_2, order_1000, order_1001 のような ID を実際に生成してみると、
「連番生成ユーティリティを“用途ごとに分けて使う”感覚」がしっかり身についてきます。

ここまで来れば、あなたはもう
「とりあえず let n = 0」から卒業して、
「設計された連番生成」を業務コードに組み込める状態です。

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