GUID / UUIDの作成方法は?


4180

JavaScriptでグローバルに一意の識別子を作成しようとしています。すべてのブラウザで使用できるルーチン、組み込みの乱数ジェネレータがどのように「ランダム」でシードされているかなどはわかりません。

GUID / UUIDは32文字以上にする必要があり、ASCIIの範囲内に収めて、パススルー時の問題を回避する必要があります。


13
文字列として表現されるときのGUIDは、長さが36文字以上38文字以下であり、パターン^ \ {?[a-zA-Z0-9] {36}?\} $に一致するため、常にASCIIです。
AnthonyWJones 2008

2
でデビッドバウははるかに良い、seedable乱数ジェネレータを提供しdavidbau.com/archives/2010/01/30/...私がUUIDを生成するには、わずかに異なるアプローチを書き上げましたblogs.cozi.com/tech/2010/04/generating- uuids-in-javascript.html
ジョージV.ライリー

まだ誰もこれについて言及していないのは奇妙ですが、完全を期すため、npmには大量のGUIDジェネレーターがあり、それらのほとんどはブラウザーでも動作することを望んでいます。
ジョージマウアー2014

回答:


2339

RFC 4122によれば、GUID(Globally Unique IDentifier)とも呼ばれるUUID(Universally Unique IDentifier)は、特定の一意性を保証するように設計された識別子です。

JSの数行でRFC準拠のUUIDを実装することは可能ですが(たとえば、以下の@broofaの回答を参照)、いくつかの一般的な落とし穴があります。

  • IDの形式が無効です(UUIDの形式は " xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx" である必要があります。xは[0-9、af]のいずれかで、Mは[1-5]のいずれかで、Nは[8、9、a、またはb]です
  • ランダム性の低品質ソース(などMath.random)の使用

したがって、本番環境用のコードを作成する開発者は、uuidモジュールなどの厳格でメンテナンスの行き届いた実装を使用することをお勧めします。


186
実際、RFCでは、乱数から作成されたUUIDが許可されています。あなたはそれをそのように識別するためにいくつかのビットをいじる必要があります。セクション4.4を参照してください。真に乱数または疑似乱数からUUIDを作成するためのアルゴリズム:rfc-archive.org/getrfc.php?rfc
Jason DeFontes

このスレッドのすべてにすでに基づいて、私は以下の「e7」バリアントの2倍の速さのバージョン、crypto-strongを作成しました。それは、ここに含まれるので、5月17日、2020年に私の名前を持つ新しい答えを探すために大きすぎる
ベネットBarouch

ノードUUIDは、今となっているUUID (後者のプロジェクトにマージした後)
Catweazle

4115

以下のためにRFC4122バージョン4に準拠し解決策、このワンライナー(っぽい)ソリューションは、最もコンパクトな私が思い付くことができます:

function uuidv4() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}

console.log(uuidv4());

更新、2015-06-02:UUIDの一意性は、基礎となる乱数ジェネレータ(RNG)に大きく依存していることに注意してください。上記のソリューションではMath.random()簡潔にするために使用していますが、高品質のRNGであるとMath.random()限りません。詳細については、Math.random()に関する Adam Hylandの優れた記事を参照してください。より堅牢なソリューションについては、高品質のRNG APIを使用するuuidモジュールの使用を検討してください。

更新、2015-08-26:補足として、この要点は、衝突の特定の確率に達する前に生成できるIDの数を決定する方法を説明しています。たとえば、3.26x10 15バージョン4 RFC4122 UUIDを使用すると、100万分の1の確率で衝突が発生します。

更新、2017-06-28:Chrome、Firefox、およびSafariにおけるMath.random PRNGの品質の状態について説明するChrome開発者から優れた記事。tl; dr-2015年後半の時点では「かなり良い」ですが、暗号品質ではありません。この問題に対処するために、ES6、cryptoAPI、および私が信用できない少しのJSウィザードを使用する上記のソリューションの更新バージョンを次に示します。

function uuidv4() {
  return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  );
}

console.log(uuidv4());

更新、2020-01-06:JS言語の一部として標準モジュールの作成に関する提案がありuuidます


30
私は衝突についての質問投稿stackoverflow.com/questions/6906916/...
MUXA

4
@marc-Math.random()の品質が問題です。しかし、xブラウザーをほぼ確実に変化させる、基礎となる実装の詳細な分析なしでは、衝突の実際の確率を知ることはできません。簡単にするために、ランダム性の理想的なソースを想定しています。しかし、そうです、muxaの問題が強調しているように、それは危険な仮定になる可能性があります。また、node-uuid( github.com/broofa/node-uuid)では、パフォーマンスが低下しても、Math.random()よりも暗号品質のランダム性を保証する他のAPIを好むためです。
ブロファ

144
確かに@Muxaの質問への答えは「いいえ」ですか?クライアントから来たものを信頼することは決して安全ではありません。ユーザーがjavascriptコンソールを起動して手動で変数を変更し、必要なものに変更する可能性がどの程度あるかによります。または、彼らが望むIDをPOSTするだけでもかまいません。また、ユーザーが自分のIDを選択して脆弱性を引き起こすかどうかにも依存します。どちらの方法でも、テーブルに入力するのが乱数IDの場合は、おそらくサーバー側で生成するので、プロセスを制御できることがわかります。
カムジャクソン

36
@DrewNoakes-UUIDは、完全にランダムな#の文字列だけではありません。「4」はuuidバージョンです(4 =「ランダム」)。「y」は、uuidバリアント(基本的にフィールドレイアウト)を埋め込む必要がある場所を示します。詳細については、ietf.org / rfc / rfc4122.txtのセクション4.1.1および4.1.3を参照してください。
broofa

5
なぜのc== 'x'代わりにc === 'x'。jshintが失敗したため。
Fizer Khan

810

私はBroofaの答えがいかにクリーンであるかを本当に気に入っていますが、貧弱な実装でMath.randomは衝突の可能性を残しています。

これは同様のRFC4122です最初の13桁の16進数をタイムスタンプの16進数部分でオフセットし、一度ページロード以降のマイクロ秒の16進数部分でオフセットを使い果たして、この問題を解決バージョン4準拠のソリューションを次に示します。このようMath.randomに、同じシード上にある場合でも、両方のクライアントは、ページロード(高パフォーマンスの時間がサポートされている場合)から正確に同じマイクロ秒数でUUIDを生成し、正確に同じミリ秒(または10,000+年後)でUUIDを生成する必要があります。同じUUIDを取得します。

function generateUUID() { // Public Domain/MIT
    var d = new Date().getTime();//Timestamp
    var d2 = (performance && performance.now && (performance.now()*1000)) || 0;//Time in microseconds since page-load or 0 if unsupported
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random() * 16;//random number between 0 and 16
        if(d > 0){//Use timestamp until depleted
            r = (d + r)%16 | 0;
            d = Math.floor(d/16);
        } else {//Use microseconds since page-load if supported
            r = (d2 + r)%16 | 0;
            d2 = Math.floor(d2/16);
        }
        return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
    });
}

console.log(generateUUID())


ここでテストするフィドルがあります。


31
覚えておいてください、new Date().getTime()ミリ秒ごとに更新されません。これがアルゴリズムの予想されるランダム性にどのように影響するかはわかりません。
devios1 2012年

84
performance.nowはさらに優れています。Date.nowとは異なり、によって返されるタイムスタンプはperformance.now()1ミリ秒の解像度に限定されません。代わりに、時間を最大マイクロ秒の精度の浮動小数点数として表します。また、Date.nowとは異なり、performance.now()によって返される値は、手動で調整されたり、ネットワークタイムプロトコルなどのソフトウェアによって歪められたりするシステムクロックとは無関係に、常に一定の割合増加します。
daniellmb 2014年

6
@daniellmbポリフィルではなく実際のドキュメントを表示するには、MDNなどにリンクしているはずです;)
Martin

2
丸めの用途はd = Math.floor(d/16);何ですか?
Praveen

2
@Praveenその操作は、タイムスタンプを16進数で1桁右にシフトし、残りを破棄します。その目的は、先ほど使用した16進数(最下位のもの)を取り除き、次の反復に備えることです。
Briguy37 2014

431

broofaの答えは、実際にはかなり洗練されています。印象的に賢く、本当に... rfc4122に準拠しており、多少読みやすく、コンパクトです。驚くばかり!

しかし、その正規表現、それらの多くのreplace()コールバック、関数呼び出しtoString()、およびMath.random()関数呼び出し(彼は結果の4ビットのみを使用し、残りを無駄にしている)を見ていると、パフォーマンスについて疑問に思われるかもしれません。確かに、joelptはで一般的なGUIDの速度を求めるためにRFCを廃止することさえ決定しましたgenerateQuickGUID

しかし、速度 RFCへの準拠を取得できますか?はい、そうです! 読みやすさを維持できますか?ええと...そんなことはないけど、ついていけば簡単です。

しかし、最初に、私の結果は、ブロッファと比較してguid(受け入れられた回答)、rfcに準拠していませんgenerateQuickGuid

                  Desktop   Android
           broofa: 1617ms   12869ms
               e1:  636ms    5778ms
               e2:  606ms    4754ms
               e3:  364ms    3003ms
               e4:  329ms    2015ms
               e5:  147ms    1156ms
               e6:  146ms    1035ms
               e7:  105ms     726ms
             guid:  962ms   10762ms
generateQuickGuid:  292ms    2961ms
  - Note: 500k iterations, results will vary by browser/cpu.

最適化の6回目の反復までに、私は最も人気のある回答を12 以上、受け入れられた回答を9 以上上回りました、とすることにより、高速非対応の答え2〜3倍。そして、私はまだrfc4122に準拠しています。

どのように興味がありますか?完全なソースをhttp://jsfiddle.net/jcward/7hyaC/3/ http://jsperf.com/uuid-generator-opt/4に配置しました

説明のために、broofaのコードから始めましょう:

function broofa() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
}

console.log(broofa())

したがってx、ランダムな16進数yとランダムなデータ(10RFC仕様に従って上位2ビットを強制することを除く)に置き換えられ、正規表現は- or 4文字としないため、それらを処理する必要はありません。とても、とても滑らかです。

最初に知っておくべきことは、正規表現と同様に関数呼び出しが高価であることです(彼は1つしか使用しませんが、マッチごとに1つずつ、32個のコールバックを持ち、32個のコールバックのそれぞれでMath.random()とvを呼び出します。 toString(16))。

パフォーマンスに向けた最初のステップは、RegExとそのコールバック関数を削除し、代わりに単純なループを使用することです。これは、-4文字を処理する必要があるのに対し、ブルームは処理しなかったことを意味します。また、文字列配列のインデックス作成を使用して、洗練された文字列テンプレートアーキテクチャを維持できることに注意してください。

function e1() {
    var u='',i=0;
    while(i++<36) {
        var c='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'[i-1],r=Math.random()*16|0,v=c=='x'?r:(r&0x3|0x8);
        u+=(c=='-'||c=='4')?c:v.toString(16)
    }
    return u;
}

console.log(e1())

基本的に、-またはを確認することを除いて同じ内部ロジック、4および(replace()コールバックの代わりに)whileループを使用すると、ほぼ3倍の改善が得られます!

次のステップは、デスクトップでの小さなステップですが、モバイルではまともな違いを生み出します。Math.random()呼び出しを減らして、ランダムなビットの87%を捨てるのではなく、ランダムなバッファーを使用して、反復ごとにシフトアウトする代わりに、それらのすべてのランダムなビットを利用しましょう。それが役立つ場合に備えて、そのテンプレート定義をループの外に移動しましょう:

function e2() {
    var u='',m='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',i=0,rb=Math.random()*0xffffffff|0;
    while(i++<36) {
        var c=m[i-1],r=rb&0xf,v=c=='x'?r:(r&0x3|0x8);
        u+=(c=='-'||c=='4')?c:v.toString(16);rb=i%8==0?Math.random()*0xffffffff|0:rb>>4
    }
    return u
}

console.log(e2())

これにより、プラットフォームに応じて10〜30%節約できます。悪くない。しかし、次の大きなステップでは、toString関数呼び出しを完全に排除し、従来の最適化であるルックアップテーブルを使用します。単純な16要素のルックアップテーブルは、toString(16)の処理をはるかに短時間で実行します。

function e3() {
    var h='0123456789abcdef';
    var k='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
    /* same as e4() below */
}
function e4() {
    var h=['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
    var k=['x','x','x','x','x','x','x','x','-','x','x','x','x','-','4','x','x','x','-','y','x','x','x','-','x','x','x','x','x','x','x','x','x','x','x','x'];
    var u='',i=0,rb=Math.random()*0xffffffff|0;
    while(i++<36) {
        var c=k[i-1],r=rb&0xf,v=c=='x'?r:(r&0x3|0x8);
        u+=(c=='-'||c=='4')?c:h[v];rb=i%8==0?Math.random()*0xffffffff|0:rb>>4
    }
    return u
}

console.log(e4())

次の最適化は別の古典です。ループの反復ごとに4ビットの出力のみを処理しているので、ループの数を半分にして、反復ごとに8ビットを処理します。RFC準拠のビット位置を処理する必要があるため、これはトリッキーですが、それほど難しくありません。次に、0x00〜0xffを格納するために、より大きなルックアップテーブル(16x16、または256)を作成する必要があり、e5()関数の外で1回だけ作成します。

var lut = []; for (var i=0; i<256; i++) { lut[i] = (i<16?'0':'')+(i).toString(16); }
function e5() {
    var k=['x','x','x','x','-','x','x','-','4','x','-','y','x','-','x','x','x','x','x','x'];
    var u='',i=0,rb=Math.random()*0xffffffff|0;
    while(i++<20) {
        var c=k[i-1],r=rb&0xff,v=c=='x'?r:(c=='y'?(r&0x3f|0x80):(r&0xf|0x40));
        u+=(c=='-')?c:lut[v];rb=i%4==0?Math.random()*0xffffffff|0:rb>>8
    }
    return u
}

console.log(e5())

引き続き256要素のLUTを使用して、一度に16ビットを処理するe6()を試しましたが、最適化の効果が減少していることがわかりました。反復は少なかったものの、処理の増加により内部ロジックは複雑になり、デスクトップでも同じように実行され、モバイルでは約10%高速でした。

適用する最後の最適化手法-ループを展開します。ループ回数は決まっているので、技術的にはすべて手作業で書き出すことができます。私は、再割り当てし続けた単一のランダム変数rでこれを1回試しましたが、パフォーマンスは低下しました。しかし、4つの変数にランダムデータを事前に割り当て、次にルックアップテーブルを使用して、適切なRFCビットを適用することで、このバージョンはすべての変数をスモークします。

var lut = []; for (var i=0; i<256; i++) { lut[i] = (i<16?'0':'')+(i).toString(16); }
function e7()
{
    var d0 = Math.random()*0xffffffff|0;
    var d1 = Math.random()*0xffffffff|0;
    var d2 = Math.random()*0xffffffff|0;
    var d3 = Math.random()*0xffffffff|0;
    return lut[d0&0xff]+lut[d0>>8&0xff]+lut[d0>>16&0xff]+lut[d0>>24&0xff]+'-'+
    lut[d1&0xff]+lut[d1>>8&0xff]+'-'+lut[d1>>16&0x0f|0x40]+lut[d1>>24&0xff]+'-'+
    lut[d2&0x3f|0x80]+lut[d2>>8&0xff]+'-'+lut[d2>>16&0xff]+lut[d2>>24&0xff]+
    lut[d3&0xff]+lut[d3>>8&0xff]+lut[d3>>16&0xff]+lut[d3>>24&0xff];
}

console.log(e7())

Modualized: http://jcward.com/UUID.js -UUID.generate()

面白いことに、16バイトのランダムデータを生成するのは簡単です。トリック全体は、それをRFC準拠の文字列形式で表現することであり、16バイトのランダムデータ、展開されたループ、およびルックアップテーブルで最も厳密に達成されます。

私の論理が正しいことを願っています-この種の面倒なビットワークで間違いを犯すのは非常に簡単です。しかし、出力は私にはよく見えます。コードの最適化によってこの狂った乗り心地を楽しんだことを願っています!

注意してください:私の主な目標は、潜在的な最適化戦略を示し、教えることでした。他の回答では、衝突や真の乱数など、適切なUUIDを生成するために重要な重要なトピックについて説明します。


14
このコードには、まだいくつかのエラーが含まれています。Math.random()*0xFFFFFFFF行はMath.random()*0x100000000完全なランダム性のためであり、値を符号なしに保つ>>>0代わりに使用する必要が|0あります(ただし、現在のコードでは、署名されていても問題はないと思います)。最後に、最近使用できるwindow.crypto.getRandomValues場合は非常に良いアイデアであり、絶対に必要な場合にのみMath.randomにフォールバックします。Math.randomのエントロピーは128ビット未満である可能性が高く、その場合、必要以上に衝突に対して脆弱になります。
デイブ

このスレッドにすでにあるものすべてに基づいて、「e7」の2倍の速度で構築し、ノードを含むすべての環境を移植でき、Math.random()から暗号強度のランダム性にアップグレードしました。uuidに暗号強度が必要だとは思わないかもしれませんが、それは、uuidの全体的なポイントである衝突の可能性がさらに低いことを意味します。コメントに収めるには大きすぎるため、個別に投稿しました。
Bennett Barouch

164

RFC 4122のセクション4.4(真の乱数または疑似乱数からUUIDを作成するためのアルゴリズム)に基づくコードを次に示します。

function createUUID() {
    // http://www.ietf.org/rfc/rfc4122.txt
    var s = [];
    var hexDigits = "0123456789abcdef";
    for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
    s[8] = s[13] = s[18] = s[23] = "-";

    var uuid = s.join("");
    return uuid;
}

4
GUIDを作成するときに動的にサイズを変更するのではなく、事前に配列サイズを宣言する必要があります。var s = new Array(36);
MgSam 2013年

1
この行には、clock_seq_hi_and_reservedのビット6〜7を01に設定する非常にマイナーなバグがあると思います。s[19]は文字 '0' .. 'f'であり、int 0x0..0xfではありません。 [19]&0x3)| 0x8はランダムに分散されません-'9'が多く、 'b'が少なくなる傾向があります。これは、何らかの理由でランダム分布を気にする場合にのみ、違いを生じます。
John Velonis 2013

153
let uniqueId = Math.random().toString(36).substring(2) + Date.now().toString(36);

IDが1ミリ秒以上離れて生成される場合、それらは100%一意です。

2つのIDが短い間隔で生成され、ランダムな方法が真にランダムであると仮定すると、グローバルに一意である可能性が99.99999999999999%のIDが生成されます(10 ^ 15の1で衝突)

数字を追加することでこの数を増やすことができますが、100%の一意のIDを生成するには、グローバルカウンターを使用する必要があります。

RFC互換性が必要な場合、このフォーマットは有効なバージョン4 GUIDとして渡されます。

let u = Date.now().toString(16) + Math.random().toString(16) + '0'.repeat(16);
let guid = [u.substr(0,8), u.substr(8,4), '4000-8' + u.substr(13,3), u.substr(16,12)].join('-');

編集:上記のコードは意図に従っていますが、RFCのレターではありません。他の不一致の中でも、それはいくつかのランダムな数字が短いです。(必要に応じてランダムな数字を追加します)利点は、これが本当に速いことです:) ここでGUIDの有効性をテストできます


4
これはUUIDではありませんか?
Marco Kerwitz

いいえ。UUID/ GUIDは122ビット(+ 6予約ビット)の数値です。グローバルカウンターサービスを通じて一意性を保証する場合がありますが、多くの場合、時間、MACアドレス、およびランダム性を中継します。UUIDはランダムではありません!ここで提案するUIDは完全には圧縮されていません。それを122ビット整数に圧縮し、6つの定義済みビットと追加のランダムビットを追加し(いくつかのタイマービットを削除)、最終的に完全に形成されたUUID / GUIDになるため、16進数に変換する必要があります。私には、IDの長さへの準拠以外は何も追加されません。
SimonRigét2018

5
仮想マシンの一意性を確保するためにMACアドレスを中継することはお勧めできません。
SimonRigét18年

1
私はこのようなことをしますが、先頭の文字とダッシュをいくつか[slug, date, random].join("_")使用します(たとえば、を作成しますusr_1dcn27itd_hj6onj6phr。これにより、IDが「作成場所」フィールドとしても使用されます
Seph Reed

95

形式の文字列ジェネレーターメソッドのような最速のGUID XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX。これは、標準に準拠したGUIDを生成しません。

この実装の1千万回の実行には32.5秒しかかかりません。これは、私がブラウザで見た中で最速です(ループ/反復のない唯一のソリューション)。

関数は次のように単純です。

/**
 * Generates a GUID string.
 * @returns {string} The generated GUID.
 * @example af8a8416-6e18-a307-bd9c-f2c947bbb3aa
 * @author Slavik Meltser.
 * @link http://slavik.meltser.info/?p=142
 */
function guid() {
    function _p8(s) {
        var p = (Math.random().toString(16)+"000000000").substr(2,8);
        return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ;
    }
    return _p8() + _p8(true) + _p8(true) + _p8();
}

パフォーマンスをテストするには、次のコードを実行できます。

console.time('t'); 
for (var i = 0; i < 10000000; i++) { 
    guid(); 
};
console.timeEnd('t');

ほとんどの方は私がそこで行ったことを理解していると思いますが、説明が必要な人が少なくとも1人はいるでしょう。

アルゴリズム:

  • このMath.random()関数は、小数点以下16桁の0〜1の10進数を返します(例:)0.4363923368509859
  • 次に、この数値を取得し、それを16を底とする文字列に変換します(上記の例から取得します 0.6fb7687f)。
    Math.random().toString(16)
  • 次に、0.プレフィックス(0.6fb7687f=> 6fb7687f)を切り取り、8桁の16進数の文字列を取得します。
    (Math.random().toString(16).substr(2,8)
  • 末尾のゼロのために、Math.random()関数はより短い数値(たとえば0.4363)を返すことがあります(上の例から、実際には数値はです0.4363000000000000)。そのため、この文字列"000000000"(9つのゼロを持つ文字列)に追加し、substr()関数でそれを切り取って、9文字にする(右にゼロを埋める)ようにしています。
  • 正確に9つのゼロを追加する理由は、Math.random()関数が正確に0または1を返すという最悪のシナリオのためです(それぞれの1/10 ^ 16の確率)。そのため、9個のゼロを追加するか("0"+"000000000"または"1"+"000000000")、2番目のインデックス(3番目の文字)から8文字の長さで切り捨てる必要がありました。残りのケースでは、ゼロを追加しても結果が損なわれることはありません。
    Math.random().toString(16)+"000000000").substr(2,8)

アセンブリ:

  • GUIDの形式は次のとおりですXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
  • 私は4個、2種類(またはフォーマット)に分割し、各部分にGUIDを分け:XXXXXXXXおよび-XXXX-XXXX
  • 次のように、これら2つのタイプを使用してGUIDを構築し、4つの呼び出しでGUIDをアセンブルしますXXXXXXXX -XXXX-XXXX -XXXX-XXXX XXXXXXXX
  • これら2つのタイプを区別するために、ペア作成関数_p8(s)にフラグパラメーターを追加しました。このsパラメーターは、ダッシュを追加するかどうかを関数に指示します。
  • 最終的に、次のチェーンを使用してGUIDを構築します_p8() + _p8(true) + _p8(true) + _p8()。それを返します。

私のブログのこの投稿へのリンク

楽しい!:-)


13
この実装は正しくありません。GUIDの特定の文字には特別な処理が必要です(たとえば、13桁目は4である必要があります)。
JLRishe 2013年

67

以下は、トップ投票の回答Chromeの衝突の回避策の組み合わせです。

generateGUID = (typeof(window.crypto) != 'undefined' && 
                typeof(window.crypto.getRandomValues) != 'undefined') ?
    function() {
        // If we have a cryptographically secure PRNG, use that
        // /programming/6906916/collisions-when-generating-uuids-in-javascript
        var buf = new Uint16Array(8);
        window.crypto.getRandomValues(buf);
        var S4 = function(num) {
            var ret = num.toString(16);
            while(ret.length < 4){
                ret = "0"+ret;
            }
            return ret;
        };
        return (S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));
    }

    :

    function() {
        // Otherwise, just use Math.random
        // /programming/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
            return v.toString(16);
        });
    };

テストしたい場合はjsbinで。


3
最初のバージョンである `window.crypto.getRandomValues , does not keep the Version 4 UUIDs format defined by RFC 4122. That is instead of xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`が生成することに注意してくださいxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
humanityANDpeace

66

これは完全に非準拠ですが、ASCIIセーフのGUIDのような一意の識別子を生成するための非常にパフォーマンスの高い実装です。

function generateQuickGuid() {
    return Math.random().toString(36).substring(2, 15) +
        Math.random().toString(36).substring(2, 15);
}

26 [a-z0-9]文字を生成し、RFC準拠のGUIDよりも短くてユニークなUIDを生成します。人間の読みやすさが重要な場合は、ダッシュを簡単に追加できます。

この関数の使用例とタイミング、およびこの質問の他の回答のいくつかを次に示します。タイミングはChrome m25で実行され、それぞれ1,000万回反復されました。

>>> generateQuickGuid()
"nvcjf1hs7tf8yyk4lmlijqkuo9"
"yq6gipxqta4kui8z05tgh9qeel"
"36dh5sec7zdj90sk2rx7pjswi2"
runtime: 32.5s

>>> GUID() // John Millikin
"7a342ca2-e79f-528e-6302-8f901b0b6888"
runtime: 57.8s

>>> regexGuid() // broofa
"396e0c46-09e4-4b19-97db-bd423774a4b3"
runtime: 91.2s

>>> createUUID() // Kevin Hakanson
"403aa1ab-9f70-44ec-bc08-5d5ac56bd8a5"
runtime: 65.9s

>>> UUIDv4() // Jed Schmidt
"f4d7d31f-fa83-431a-b30c-3e6cc37cc6ee"
runtime: 282.4s

>>> Math.uuid() // broofa
"5BD52F55-E68F-40FC-93C2-90EE069CE545"
runtime: 225.8s

>>> Math.uuidFast() // broofa
"6CB97A68-23A2-473E-B75B-11263781BBE6"
runtime: 92.0s

>>> Math.uuidCompact() // broofa
"3d7b7a06-0a67-4b67-825c-e5c43ff8c1e8"
runtime: 229.0s

>>> bitwiseGUID() // jablko
"baeaa2f-7587-4ff1-af23-eeab3e92"
runtime: 79.6s

>>>> betterWayGUID() // Andrea Turri
"383585b0-9753-498d-99c3-416582e9662c"
runtime: 60.0s

>>>> UUID() // John Fowler
"855f997b-4369-4cdb-b7c9-7142ceaf39e8"
runtime: 62.2s

これがタイミングコードです。

var r;
console.time('t'); 
for (var i = 0; i < 10000000; i++) { 
    r = FuncToTest(); 
};
console.timeEnd('t');

62

ここでは、ユーザがコメントから2011年10月9日付けのソリューションですJEDhttps://gist.github.com/982883は

UUIDv4 = function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)}

これにより、現在の最高評価の回答と同じ目標が達成されますが、強制、再帰、および指数表記を利用することにより、50バイト以上のバイト数が削減されます。それがどのように機能するのか知りたい人のために、ここに関数の古いバージョンの注釈付きフォームがあります:

UUIDv4 =

function b(
  a // placeholder
){
  return a // if the placeholder was passed, return
    ? ( // a random number from 0 to 15
      a ^ // unless b is 8,
      Math.random() // in which case
      * 16 // a random number from
      >> a/4 // 8 to 11
      ).toString(16) // in hexadecimal
    : ( // or otherwise a concatenated string:
      [1e7] + // 10000000 +
      -1e3 + // -1000 +
      -4e3 + // -4000 +
      -8e3 + // -80000000 +
      -1e11 // -100000000000,
      ).replace( // replacing
        /[018]/g, // zeroes, ones, and eights with
        b // random hex digits
      )
}

52

鷺shkedyの技術ブログ

function generateGuid() {
  var result, i, j;
  result = '';
  for(j=0; j<32; j++) {
    if( j == 8 || j == 12 || j == 16 || j == 20) 
      result = result + '-';
    i = Math.floor(Math.random()*16).toString(16).toUpperCase();
    result = result + i;
  }
  return result;
}

ActiveXコントロールの使用を含む他の方法がありますが、これらには近づかないでください!

編集: GUIDジェネレーターが一意のキーを保証できないことを指摘する価値があると思いました(ウィキペディアの記事を確認してください)。衝突の可能性は常にあります。GUIDは、衝突の変化をほとんどなくすのに十分な大きさのキーユニバースを提供します。


8
一意性を保証するものではないため、これは技術的な意味でのGUIDではないことに注意してください。これは、アプリケーションによっては問題にならない場合があります。
Stephen Deken 2008

2
パフォーマンスに関する簡単なメモ。このソリューションは、単一の結果を取得するために合計36個の文字列を作成します。パフォーマンスが重要な場合は、次の推奨事項に従ってアレイを作成して結合することを検討してください: tinyurl.com/y37xtx さらなる調査では問題にならない可能性があるため、YMMV: tinyurl.com/3l7945
Brandon DuRette

2
一意性については、バージョン1、3、および5のUUIDがバージョン4とは異なり、確定的であることは注目に値します。これらのUUIDジェネレーターへの入力(v1のノードID、v3とv5の名前空間と名前)が一意である場合(想定されているとおり)、結果のUUIDは一意になります。理論的には、とにかく。
ブローファ2017年

41

node-uuid(https://github.com/kelektiv/node-uuid)を使用できます

RFC4122 UUIDSのシンプルで高速な生成。

特徴:

  • RFC4122バージョン1またはバージョン4 UUIDを生成する
  • node.jsとブラウザで実行されます。
  • サポートするプラットフォームでの暗号的に強力なランダムな#生成。
  • 小さなフットプリント(何かもっと小さくしたいですか?これをチェックしてください!

NPMを使用したインストール:

npm install uuid

またはブラウザ経由でuuidを使用する:

生ファイルのダウンロード(uuid v1):https ://raw.githubusercontent.com/kelektiv/node-uuid/master/v1.js生ファイルの ダウンロード(uuid v4):https : //raw.githubusercontent.com/kelektiv/node -uuid / master / v4.js


さらに小さくしたいですか?これをチェックしてくださいhttps//gist.github.com/jed/982883


使用法:

// Generate a v1 UUID (time-based)
const uuidV1 = require('uuid/v1');
uuidV1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'

// Generate a v4 UUID (random)
const uuidV4 = require('uuid/v4');
uuidV4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'

// Generate a v5 UUID (namespace)
const uuidV5 = require('uuid/v5');

// ... using predefined DNS namespace (for domain names)
uuidV5('hello.example.com', v5.DNS)); // -> 'fdda765f-fc57-5604-a269-52a7df8164ec'

// ... using predefined URL namespace (for, well, URLs)
uuidV5('http://example.com/hello', v5.URL); // -> '3bbcee75-cecc-5b56-8031-b6641c1ed1f1'

// ... using a custom namespace
const MY_NAMESPACE = '(previously generated unique uuid string)';
uuidV5('hello', MY_NAMESPACE); // -> '90123e1c-7512-523e-bb28-76fab9f2f73d'

ES6:

import uuid from 'uuid/v4';
const id = uuid();

34
var uuid = function() {
    var buf = new Uint32Array(4);
    window.crypto.getRandomValues(buf);
    var idx = -1;
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        idx++;
        var r = (buf[idx>>3] >> ((idx%8)*4))&15;
        var v = c == 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
};

編集:

この機能を使用していて、冗長性が嫌いだった私のプロジェクトを再検討しました。-しかし、適切なランダム性が必要でした。

Briguy37の回答と、バッファからニブルサイズのウィンドウを抽出するいくつかのビット単位の演算子に基づくバージョン。

前回、JavaのUUIDで非準拠のUUIDを解析するときに問題が発生したため、RFCタイプ4(ランダム)スキーマに準拠する必要があります。


31

このスレッドのベストアンサーの組み合わせとしての単純なJavaScriptモジュール。

var crypto = window.crypto || window.msCrypto || null; // IE11 fix

var Guid = Guid || (function() {

  var EMPTY = '00000000-0000-0000-0000-000000000000';

  var _padLeft = function(paddingString, width, replacementChar) {
    return paddingString.length >= width ? paddingString : _padLeft(replacementChar + paddingString, width, replacementChar || ' ');
  };

  var _s4 = function(number) {
    var hexadecimalResult = number.toString(16);
    return _padLeft(hexadecimalResult, 4, '0');
  };

  var _cryptoGuid = function() {
    var buffer = new window.Uint16Array(8);
    window.crypto.getRandomValues(buffer);
    return [_s4(buffer[0]) + _s4(buffer[1]), _s4(buffer[2]), _s4(buffer[3]), _s4(buffer[4]), _s4(buffer[5]) + _s4(buffer[6]) + _s4(buffer[7])].join('-');
  };

  var _guid = function() {
    var currentDateMilliseconds = new Date().getTime();
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(currentChar) {
      var randomChar = (currentDateMilliseconds + Math.random() * 16) % 16 | 0;
      currentDateMilliseconds = Math.floor(currentDateMilliseconds / 16);
      return (currentChar === 'x' ? randomChar : (randomChar & 0x7 | 0x8)).toString(16);
    });
  };

  var create = function() {
    var hasCrypto = crypto != 'undefined' && crypto !== null,
      hasRandomValues = typeof(window.crypto.getRandomValues) != 'undefined';
    return (hasCrypto && hasRandomValues) ? _cryptoGuid() : _guid();
  };

  return {
    newGuid: create,
    empty: EMPTY
  };
})();

// DEMO: Create and show GUID
console.log(Guid.newGuid());

使用法:

Guid.newGuid()

「c6c2d12f-d76b-5739-e551-07e6de5b0807」

Guid.empty

「00000000-0000-0000-0000-000000000000」


1
何を気にされるすべての答えは、それが思われることでOK JavaScriptを格納するためGUIDとしてstring。あなたの答えは、少なくともを使用して、はるかに効率的なストレージに取り組みUint16Arrayます。toString関数はJavaScriptでバイナリ表現を使用する必要がありますobject
セバスチャン

このコードによって生成されるこのUUIDは、RFCに準拠しているが弱い(_guid)、またはRFCに準拠していないが強い(_cryptoGuid)のいずれかです。前者はMath.random()を使用しますが、これは貧弱なRNGであることが現在知られています。後者は、バージョンとバリアントのフィールドの設定に失敗しています。
ブローファ2017年

@broofa-強力 RFC準拠にするために何を提案しますか?そして、_cryptoGuidがRFCに準拠していないのはなぜですか?
Matt

@Matt _cryptoGuid()は、128ビットすべてをランダムに設定します。つまり、RFCで説明されているように、バージョンとバリアントのフィールドを設定しません。strong +準拠の実装については、上記の私の最高の回答でcrypto.getRandomValues()を使用するuuidv4()の代替実装を参照してください。
ブローファ2018年

29

これは、バージョン4のUUID(疑似乱数から作成)を作成します。

function uuid()
{
   var chars = '0123456789abcdef'.split('');

   var uuid = [], rnd = Math.random, r;
   uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
   uuid[14] = '4'; // version 4

   for (var i = 0; i < 36; i++)
   {
      if (!uuid[i])
      {
         r = 0 | rnd()*16;

         uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf];
      }
   }

   return uuid.join('');
}

次に、生成されたUUIDのサンプルを示します。

682db637-0f31-4847-9cdf-25ba9613a75c
97d19478-3ab2-4aa1-b8cc-a1c3540f54aa
2eed04c9-2692-456d-a0fd-51012f947136

28

ええと、これには既にたくさんの答えがありますが、残念ながら、その中に「本当の」ランダムはありません。以下のバージョンは、ブロッファの答えを採用したものですが、利用可能な場合は暗号ライブラリを使用する「真の」ランダム関数とフォールバックとしてのAlea()関数を含むように更新されています。

  Math.log2 = Math.log2 || function(n){ return Math.log(n) / Math.log(2); }
  Math.trueRandom = (function() {
  var crypt = window.crypto || window.msCrypto;

  if (crypt && crypt.getRandomValues) {
      // if we have a crypto library, use it
      var random = function(min, max) {
          var rval = 0;
          var range = max - min;
          if (range < 2) {
              return min;
          }

          var bits_needed = Math.ceil(Math.log2(range));
          if (bits_needed > 53) {
            throw new Exception("We cannot generate numbers larger than 53 bits.");
          }
          var bytes_needed = Math.ceil(bits_needed / 8);
          var mask = Math.pow(2, bits_needed) - 1;
          // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111

          // Create byte array and fill with N random numbers
          var byteArray = new Uint8Array(bytes_needed);
          crypt.getRandomValues(byteArray);

          var p = (bytes_needed - 1) * 8;
          for(var i = 0; i < bytes_needed; i++ ) {
              rval += byteArray[i] * Math.pow(2, p);
              p -= 8;
          }

          // Use & to apply the mask and reduce the number of recursive lookups
          rval = rval & mask;

          if (rval >= range) {
              // Integer out of acceptable range
              return random(min, max);
          }
          // Return an integer that falls within the range
          return min + rval;
      }
      return function() {
          var r = random(0, 1000000000) / 1000000000;
          return r;
      };
  } else {
      // From https://web.archive.org/web/20120502223108/http://baagoe.com/en/RandomMusings/javascript/
      // Johannes Baagøe <baagoe@baagoe.com>, 2010
      function Mash() {
          var n = 0xefc8249d;

          var mash = function(data) {
              data = data.toString();
              for (var i = 0; i < data.length; i++) {
                  n += data.charCodeAt(i);
                  var h = 0.02519603282416938 * n;
                  n = h >>> 0;
                  h -= n;
                  h *= n;
                  n = h >>> 0;
                  h -= n;
                  n += h * 0x100000000; // 2^32
              }
              return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
          };

          mash.version = 'Mash 0.9';
          return mash;
      }

      // From http://baagoe.com/en/RandomMusings/javascript/
      function Alea() {
          return (function(args) {
              // Johannes Baagøe <baagoe@baagoe.com>, 2010
              var s0 = 0;
              var s1 = 0;
              var s2 = 0;
              var c = 1;

              if (args.length == 0) {
                  args = [+new Date()];
              }
              var mash = Mash();
              s0 = mash(' ');
              s1 = mash(' ');
              s2 = mash(' ');

              for (var i = 0; i < args.length; i++) {
                  s0 -= mash(args[i]);
                  if (s0 < 0) {
                      s0 += 1;
                  }
                  s1 -= mash(args[i]);
                  if (s1 < 0) {
                      s1 += 1;
                  }
                  s2 -= mash(args[i]);
                  if (s2 < 0) {
                      s2 += 1;
                  }
              }
              mash = null;

              var random = function() {
                  var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
                  s0 = s1;
                  s1 = s2;
                  return s2 = t - (c = t | 0);
              };
              random.uint32 = function() {
                  return random() * 0x100000000; // 2^32
              };
              random.fract53 = function() {
                  return random() +
                      (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
              };
              random.version = 'Alea 0.9';
              random.args = args;
              return random;

          }(Array.prototype.slice.call(arguments)));
      };
      return Alea();
  }
}());

Math.guid = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c)    {
      var r = Math.trueRandom() * 16 | 0,
          v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
  });
};

27

GitHub上のJavaScriptプロジェクト-https ://github.com/LiosK/UUID.js

UUID.js JavaScript用のRFC準拠のUUIDジェネレーター。

RFC 4122 http://www.ietf.org/rfc/rfc4122.txtを参照してください

機能RFC 4122準拠のUUIDを生成します。

バージョン4のUUID(乱数からのUUID)とバージョン1のUUID(時間ベースのUUID)が利用可能です。

UUIDオブジェクトは、UUIDフィールドへのアクセスを含む、UUIDへのさまざまなアクセスを許可します。

JavaScriptの低いタイムスタンプ解像度は、乱数によって補われます。


21
  // RFC 4122
  //
  // A UUID is 128 bits long
  //
  // String representation is five fields of 4, 2, 2, 2, and 6 bytes.
  // Fields represented as lowercase, zero-filled, hexadecimal strings, and
  // are separated by dash characters
  //
  // A version 4 UUID is generated by setting all but six bits to randomly
  // chosen values
  var uuid = [
    Math.random().toString(16).slice(2, 10),
    Math.random().toString(16).slice(2, 6),

    // Set the four most significant bits (bits 12 through 15) of the
    // time_hi_and_version field to the 4-bit version number from Section
    // 4.1.3
    (Math.random() * .0625 /* 0x.1 */ + .25 /* 0x.4 */).toString(16).slice(2, 6),

    // Set the two most significant bits (bits 6 and 7) of the
    // clock_seq_hi_and_reserved to zero and one, respectively
    (Math.random() * .25 /* 0x.4 */ + .5 /* 0x.8 */).toString(16).slice(2, 6),

    Math.random().toString(16).slice(2, 14)].join('-');

16

私はブロッファの答えを理解したかったので、それを拡大してコメントを追加しました:

var uuid = function () {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
        /[xy]/g,
        function (match) {
            /*
            * Create a random nibble. The two clever bits of this code:
            *
            * - Bitwise operations will truncate floating point numbers
            * - For a bitwise OR of any x, x | 0 = x
            *
            * So:
            *
            * Math.random * 16
            *
            * creates a random floating point number
            * between 0 (inclusive) and 16 (exclusive) and
            *
            * | 0
            *
            * truncates the floating point number into an integer.
            */
            var randomNibble = Math.random() * 16 | 0;

            /*
            * Resolves the variant field. If the variant field (delineated
            * as y in the initial string) is matched, the nibble must
            * match the mask (where x is a do-not-care bit):
            *
            * 10xx
            *
            * This is achieved by performing the following operations in
            * sequence (where x is an intermediate result):
            *
            * - x & 0x3, which is equivalent to x % 3
            * - x | 0x8, which is equivalent to x + 8
            *
            * This results in a nibble between 8 inclusive and 11 exclusive,
            * (or 1000 and 1011 in binary), all of which satisfy the variant
            * field mask above.
            */
            var nibble = (match == 'y') ?
                (randomNibble & 0x3 | 0x8) :
                randomNibble;

            /*
            * Ensure the nibble integer is encoded as base 16 (hexadecimal).
            */
            return nibble.toString(16);
        }
    );
};

詳細な説明ありがとうございます!具体的には、8〜11のケージにニブルを入れ、同等の説明を付けると非常に役立ちます。
Egor Litvinchuk

15

私自身のUUID / GUIDジェネレーターをここでいくつかの追加機能調整しまし

以下のKybosを使用しています乱数ジェネレータを暗号化を少し強化します。

以下は、baagoe.comのMashメソッドとKybosメソッドを除外したスクリプトです。

//UUID/Guid Generator
// use: UUID.create() or UUID.createSequential()
// convenience:  UUID.empty, UUID.tryParse(string)
(function(w){
  // From http://baagoe.com/en/RandomMusings/javascript/
  // Johannes Baagøe <baagoe@baagoe.com>, 2010
  //function Mash() {...};

  // From http://baagoe.com/en/RandomMusings/javascript/
  //function Kybos() {...};

  var rnd = Kybos();

  //UUID/GUID Implementation from http://frugalcoder.us/post/2012/01/13/javascript-guid-uuid-generator.aspx
  var UUID = {
    "empty": "00000000-0000-0000-0000-000000000000"
    ,"parse": function(input) {
      var ret = input.toString().trim().toLowerCase().replace(/^[\s\r\n]+|[\{\}]|[\s\r\n]+$/g, "");
      if ((/[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}/).test(ret))
        return ret;
      else
        throw new Error("Unable to parse UUID");
    }
    ,"createSequential": function() {
      var ret = new Date().valueOf().toString(16).replace("-","")
      for (;ret.length < 12; ret = "0" + ret);
      ret = ret.substr(ret.length-12,12); //only least significant part
      for (;ret.length < 32;ret += Math.floor(rnd() * 0xffffffff).toString(16));
      return [ret.substr(0,8), ret.substr(8,4), "4" + ret.substr(12,3), "89AB"[Math.floor(Math.random()*4)] + ret.substr(16,3),  ret.substr(20,12)].join("-");
    }
    ,"create": function() {
      var ret = "";
      for (;ret.length < 32;ret += Math.floor(rnd() * 0xffffffff).toString(16));
      return [ret.substr(0,8), ret.substr(8,4), "4" + ret.substr(12,3), "89AB"[Math.floor(Math.random()*4)] + ret.substr(16,3),  ret.substr(20,12)].join("-");
    }
    ,"random": function() {
      return rnd();
    }
    ,"tryParse": function(input) {
      try {
        return UUID.parse(input);
      } catch(ex) {
        return UUID.empty;
      }
    }
  };
  UUID["new"] = UUID.create;

  w.UUID = w.Guid = UUID;
}(window || this));

15

速度を考慮したrfc4122バージョン4準拠のソリューションが必要な場合(Math.random()への呼び出しが少ない):

var rand = Math.random;

function UUID() {
    var nbr, randStr = "";
    do {
        randStr += (nbr = rand()).toString(16).substr(3, 6);
    } while (randStr.length < 30);
    return (
        randStr.substr(0, 8) + "-" +
        randStr.substr(8, 4) + "-4" +
        randStr.substr(12, 3) + "-" +
        ((nbr*4|0)+8).toString(16) + // [89ab]
        randStr.substr(15, 3) + "-" +
        randStr.substr(18, 12)
    );
}

console.log( UUID() );

上記の関数は、速度とランダム性のバランスが適切でなければなりません。


13

ES6サンプル

const guid=()=> {
  const s4=()=> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);     
  return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4() + s4() + s4()}`;
}

12

より良い方法:

function(
  a,b                // placeholders
){
  for(               // loop :)
      b=a='';        // b - result , a - numeric variable
      a++<36;        // 
      b+=a*51&52  // if "a" is not 9 or 14 or 19 or 24
                  ?  //  return a random number or 4
         (
           a^15      // if "a" is not 15
              ?      // genetate a random number from 0 to 15
           8^Math.random()*
           (a^20?16:4)  // unless "a" is 20, in which case a random number from 8 to 11
              :
           4            //  otherwise 4
           ).toString(16)
                  :
         '-'            //  in other cases (if "a" is 9,14,19,24) insert "-"
      );
  return b
 }

最小化:

function(a,b){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'-');return b}

11

私は知っています、それは古い質問です。完全を期すために、ご使用の環境がSharePointの場合は、新しいGUIDを作成するSP.Guid.newGuidmsdn link)というユーティリティ関数があります。この関数は、sp.init.jsファイル内にあります。この関数を書き換えると(他のプライベート関数から他の依存関係を削除するため)、次のようになります。

var newGuid = function () {
    var result = '';
    var hexcodes = "0123456789abcdef".split("");

    for (var index = 0; index < 32; index++) {
        var value = Math.floor(Math.random() * 16);

        switch (index) {
        case 8:
            result += '-';
            break;
        case 12:
            value = 4;
            result += '-';
            break;
        case 16:
            value = value & 3 | 8;
            result += '-';
            break;
        case 20:
            result += '-';
            break;
        }
        result += hexcodes[value];
    }
    return result;
};

11

これは日付に基づいており、一意性を「保証する」ためにランダムなサフィックスを追加します。CSS識別子に適しています。それは常に次のようなものを返し、ハッキングするのは簡単です:

uid-139410573297741

var getUniqueId = function (prefix) {
            var d = new Date().getTime();
            d += (parseInt(Math.random() * 100)).toString();
            if (undefined === prefix) {
                prefix = 'uid-';
            }
            d = prefix + d;
            return d;
        };

11

サポートさcrypto.getRandomValues(a)れているブラウザー(IE11 +、iOS7 +、FF21 +、Chrome、Android Chrome)で使用する単純なコード。Math.random()衝突を引き起こす可能性があるため、使用を避けます(たとえば、実際の状況でMuxaによって生成された4000個のUUIDに対して20回の衝突)。

function uuid() {
    function randomDigit() {
        if (crypto && crypto.getRandomValues) {
            var rands = new Uint8Array(1);
            crypto.getRandomValues(rands);
            return (rands[0] % 16).toString(16);
        } else {
            return ((Math.random() * 16) | 0).toString(16);
        }
    }
    var crypto = window.crypto || window.msCrypto;
    return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/x/g, randomDigit);
}

ノート:

  • 速度ではなくコードの可読性が最適化されているため、毎秒数百のuuidに適しています。パフォーマンスを測定するためにhttp://jsbin.com/fuwigo/1を使用して私のラップトップ上のChromiumで毎秒約10000 uuid()を生成します。
  • "y"に8のみを使用すると、コードが読みやすくなります(yは8、9、A、Bのいずれでもかまいません)。

11

特定の形式ではないランダムな128ビット文字列が必要な場合は、以下を使用できます。

function uuid() {
    return crypto.getRandomValues(new Uint32Array(4)).join('-');
}

これはのようなものを返します2350143528-4164020887-938913176-2513998651


ところで、なぜ文字も生成せず、数字のみを生成するのですか?安全性が大幅に低下
vsync 2018

1
次のように文字(文字)を追加することもできます:Array.from((window.crypto || window.msCrypto).getRandomValues(new Uint32Array(4))).map(n => n.toString(16)).join('-')
magikMaker

11

変異が2つだけある、もう1つのより読みやすいバリアント。

function uuid4()
{
  function hex (s, b)
  {
    return s +
      (b >>> 4   ).toString (16) +  // high nibble
      (b & 0b1111).toString (16);   // low nibble
  }

  let r = crypto.getRandomValues (new Uint8Array (16));

  r[6] = r[6] >>> 4 | 0b01000000; // Set type 4: 0100
  r[8] = r[8] >>> 3 | 0b10000000; // Set variant: 100

  return r.slice ( 0,  4).reduce (hex, '' ) +
         r.slice ( 4,  6).reduce (hex, '-') +
         r.slice ( 6,  8).reduce (hex, '-') +
         r.slice ( 8, 10).reduce (hex, '-') +
         r.slice (10, 16).reduce (hex, '-');
}

ほとんどのjs開発者はWeb開発者であり、開発のほとんどの時間でそれらを使用しないため、ビット単位演算子の機能を理解できません。実際、私はそれらのどれも必要としませんでした、そして私は97年以来js開発者です。そのため、サンプルコードは、それを読む平均的なWeb開発者にはまだ完全に読めません。言うまでもなく、1文字の変数名を使用しているため、さらにわかりにくくなっています。おそらく、きれいなコードを読み取り、多分それは役立ちます:amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/...は
inf3rno

@ inf3rnoは彼を非難しないでください。このスレッドで提案されたすべての解決策は謎めいていますが、質問は一種のライナーを持つことを考えれば正しい答えです。それがワンライナーが謎めいたものです。彼らは平均的な開発者が読みやすいようにする余裕はありませんが、前の簡単なコメントが行う画面領域を節約します。その結果、代わりに「読み取り可能なコード」で書かれていた場合よりもずっと読みやすくなります。
tatsu

ランダム!=ユニーク
user1529413

@ user1529413はい。一意性にはインデックスが必要です。
ceving

これは私のお気に入りの答えです。これは、UUIDを16バイト(128ビット)の値として構築するものであり、シリアル化された、読みやすい形式ではないためです。文字列をドロップして、ランダムな128ビットの正しいビットを設定するのは簡単です。これは、uuidv4で必要なことです。短いURLの場合はbase64を使用して、それを一部のWebアセンブリに渡し、文字列としてよりも少ないメモリ領域に格納し、4096サイズのバッファにして256個のuuidを配置し、ブラウザのデータベースに格納するなどできます。最初からすべてを小文字の16進エンコードされた文字列として持つよりも。
ジョシュ

8

OK、uuidパッケージを使用すると、バージョン1、3、4、および5のUUIDがサポートされます。

yarn add uuid

その後:

const uuidv1 = require('uuid/v1');
uuidv1(); // ⇨ '45745c60-7b1a-11e8-9c9c-2d42b21b1a3e'

完全に指定されたオプションでそれを行うこともできます:

const v1options = {
  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
  clockseq: 0x1234,
  msecs: new Date('2011-11-01').getTime(),
  nsecs: 5678
};
uuidv1(v1options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab'

詳細については、こちらのnpmページにアクセスしてください


6

このために独自のものを作成する代わりに、複数のコントリビューターによって保守されている十分にテストされたコードを使用することが重要です。これは、Xブラウザーで機能する最短の賢いバージョンよりも最も安定したコードを好む可能性がある場所の1つですが、Yの特異性を考慮に入れないため、ランダムにのみマニフェストよりもバグの調査が非常に困難になることがよくあります一部のユーザー。個人的に私はhttps://github.com/aurigadl/uuid-jsでuuid-jsを使用しています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.