Edited at

JavaScript で UUID (Ver4)

More than 1 year has 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) を作ることができました。