Help us understand the problem. What is going on with this article?

JavaScript で UUID (Ver4)

More than 3 years have passed since last update.

なるべく衝突しないIDを用意したい

時刻やMACアドレスなどの固有の値を使わず、なるべく衝突しない一意のIDを生成したい。それでは、UUIDを作りましょう。

バージョン4

乱数によるUUID。16進表記ではRRRRRRRR-RRRR-4RRR-rRRR-RRRRRRRRRRRRとなり、バリアント(10)とバージョン(0100)を除くすべてのビットを乱数(R:122ビット)で生成する。
UUID - Wikipedia

RFC4122 でも確認できます。

他ライブラリではどのように生成しているのか

Chrome Platform Analytics の実装 (Apache License v2.0)

identifier.js
/** @private {string} */
analytics.internal.Identifier.UUID_FMT_ =
    'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';


/** @private {RegExp} */
analytics.internal.Identifier.UUID_MATCHER_ =
    /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;


/**
 * @return {string} A randomly generated UUID V4.
 */
analytics.internal.Identifier.generateUuid = function() {
  var chars = analytics.internal.Identifier.UUID_FMT_.split('');
  for (var i = 0, len = chars.length; i < len; i++) {
    switch (chars[i]) {
      case 'x':
        chars[i] = goog.math.randomInt(16).toString(16);
        break;
      case 'y':
        chars[i] = (goog.math.randomInt(4) + 8).toString(16);
        break;
    }
  }

  return chars.join('');
};
  1. analytics.internal.Identifier.UUID_FMT_ を分解
  2. 分解した文字列(chars)を1文字ずつ取得して
  3. パターンに合う文字を生成・書き換え
  4. 結合します
  • パターンに合わない文字(-4)はそのまま出力されます。
  • パターン「x」の場合は0~9またはa~fのいずれか1文字が選択されます。
  • パターン「y」の場合は89aまたはbのいずれか1文字が選択されます。

なお、.UUID_MATCHER_ は、生成済みのUUIDがパターンと合致するかテストするための正規表現となります。

上記の実装では Google Closure Library が使われています。goog.math.randomInt(number)Math.floor(Math.random() * number)に置き換える事ができます。

uuid-v4-switch.js
switch (chars[i]) {
  case "x":
    chars[i] = Math.floor(Math.random() * 16).toString(16);
    break;
  case "y":
    chars[i] = (Math.floor(Math.random() * 4) + 8).toString(16);
    break;
}

google/closure-library math.js

コードを書く

単体で生成できるようにしてみましょう。

uuid-v4.js
function generateUuid() {
    // https://github.com/GoogleChrome/chrome-platform-analytics/blob/master/src/internal/identifier.js
    // const FORMAT: string = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
    let chars = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".split("");
    for (let i = 0, len = chars.length; i < len; i++) {
        switch (chars[i]) {
            case "x":
                chars[i] = Math.floor(Math.random() * 16).toString(16);
                break;
            case "y":
                chars[i] = (Math.floor(Math.random() * 4) + 8).toString(16);
                break;
        }
    }
    return chars.join("");
}

確認する

ブラウザにて確認してみましょう。
test.png

JavaScript で UUID (Ver4) を作ることができました。

psn
私です。読んでいますか :) はぶ https://github.com/niyari
https://blog.hatena.ne.jp/psne/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした