全ブラウザで crypto.randomUUID がサポートされているため、今さらこの polyfill を実装する必要はない。しかし UUID v4 の仕組みを理解するには良い題材になる。
コード
type UUID = `${string}-${string}-${string}-${string}-${string}`;
const FN_NAME = "randomUUID";const BASE_STR = [1e7, 1e3, 4e3, 8e3, 1e11].join("-");
/** * UUID v4 を生成する * ブラウザが randomUUID をサポートしていない場合はポリフィル実装を実行 */export function randomUUID(): UUID { const api = crypto; if (FN_NAME in api) return api[FN_NAME]();
return BASE_STR.replace(/[018]/g, replacer) as UUID;}
function replacer(char: string): string { const random = crypto.getRandomValues(new Uint8Array(1))[0]; const int = Number.parseInt(char); return (int ^ (random & (15 >> (int / 4)))).toString(16);}UUID v4 の仕組み
UUID v4 はランダムに生成される 128 ビットの識別子だ。標準形式は 8-4-4-4-12 の 36 文字(ハイフン含む)。
- xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
- 13 文字目は必ず 4(バージョンを示す)
- 17 文字目は 8, 9, a, b のいずれか(variant を示す)
実装の解説
BASE_STR は “10000000-1000-4000-8000-100000000000” というテンプレートになる。replace で 0, 1, 8 の各文字をランダム値に置き換えることで UUID を生成している。
crypto.getRandomValues で暗号的に安全な乱数を取得し、ビット演算で UUID の各位置に埋め込んでいく。
注意点
- 本番コードではネイティブの crypto.randomUUID を使うべき
- この実装は学習目的向け
- パフォーマンスはネイティブ実装に劣る
hsb.horse