在JavaScript中创建GUID/UUID?

Jas*_*hen 3915 javascript uuid guid

我正在尝试在JavaScript中创建全局唯一标识符.我不确定所有浏览器上有哪些例程,"随机"和内置随机数生成器的种子等等.

GUID/UUID应至少为32个字符,并应保持在ASCII范围内,以避免传递它们时出现问题.

bro*_*ofa 3793

对于符合RFC4122版本4的解决方案,这种单线程(ish)解决方案是我能想到的最紧凑的解决方案:

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());
Run Code Online (Sandbox Code Playgroud)

更新,2015-06-02:请注意,UUID唯一性在很大程度上依赖于底层随机数生成器(RNG).上面的解决方案使用Math.random()为了简洁,但是Math.random()保证是一个高品质的RNG.有关详细信息,请参阅Adam Hyland 在Math.random()上优秀文章.对于更强大的解决方案,请考虑类似于uuid模块 [免责声明:我是作者],它使用更高质量的RNG API.

更新,2015-08-26:作为旁注,这个要点描述了如何确定在达到一定的碰撞概率之前可以生成多少个ID.例如,对于3.26x10 15版本4 RFC4122 UUID,您有一个百万分之一的碰撞机会.

更新,2017-06-28:Chrome开发人员在Chrome,Firefox和Safari中讨论Math.random PRNG质量状态的好文章.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());
Run Code Online (Sandbox Code Playgroud)

  • 当然,@ Muxa的问题的答案是'不'?信任来自客户的东西绝不是真正安全的.我想这取决于你的用户提出一个javascript控制台的可能性,并手动将变量更改为他们想要的东西.或者他们可以给你发回他们想要的id.这还取决于用户选择自己的ID是否会导致漏洞.无论哪种方式,如果它是一个随机数字ID进入一个表,我可能会生成它在服务器端,所以我知道我可以控制该过程. (131认同)
  • 使用此代码在客户端上生成唯一ID,然后使用这些ID作为主键来保存服务器上的对象是否安全? (70认同)
  • @DrewNoakes - UUID不只是一串完全随机的#."4"是uuid版本(4 ="随机")."y"标记需要嵌入uuid变体(基本上是字段布局)的位置.有关详细信息,请参阅http://www.ietf.org/rfc/rfc4122.txt的4.1.1和4.1.3节. (34认同)
  • ...(续)此功能碰撞产生的两个ID的几率在字面上是天文数字小.ID的128位中除了6位之外的所有ID都是随机生成的,这意味着对于任何两个ID,它们将发生碰撞的机会为1 ^ 2 ^^ 122(或5.3x10 ^^ 36). (30认同)
  • 我发布了一个关于碰撞的问题http://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript (30认同)
  • 我有点困惑,在 JavaScript 中 ```[1e7]+-1e3``` 并没有真正的意义,数组被添加到数字中?我缺少什么?注意:在打字稿中它不会通过 (22认同)
  • Typescript 用户:您可以在第一个数组之前添加 `<any>`,如下所示:`<any>[1e7]` - 让它通过的快速方法。 (12认同)
  • 如果你正在使用打字稿并得到错误:`uuidv4(){const foo:any = [1e7] return(foo + -1e3 + -4e3 + -8e3 + -1e11).replace(/ [018]/g,c =>( c ^ crypto.getRandomValues(new Uint8Array(1))[0]&15 >> c/4).t​​oString(16))}` (8认同)
  • 好的,我遇到了一个问题.我偶尔会发生冲突 - 在Chrome中的不同机器上生成.在过去的两个月里,我发生了大约20次碰撞(大约4000次).是Chrome吗?或者它是Javascript的随机?有解决方案吗 (6认同)
  • 我知道您在帖子中添加了很多警告,但您最好现在就删除第一个答案,很多菜鸟只会看到这个答案并复制他们看到的第一件事而不阅读其余部分。实际上,[您无法从 Math.random API 可靠地生成 UUID](https://crypto.stackexchange.com/questions/81619/is-it-possible-to-create-a-128-bit-uuid-来自弱熵源),依赖它是危险的。 (6认同)
  • 我喜欢自定义解决方案,除了其中的表达式“[1e7]+-1e3+-4e3+-8e3+-1e11”。我个人更喜欢表达“\`${1e7}-${1e3}-${4e3}-${8e3}-${1e11}\``。它有点长,但对我来说也更清晰。它还允许我轻松更改生成的 UUID 的格式。 (6认同)
  • 为什么`c =='x'`而不是`c ==='x'`.因为jshint失败了. (5认同)
  • @Ayyash 参见 https://www.destroyallsoftware.com/talks/wat (5认同)
  • 我在这样的全局函数中使用了Wrapped:function NewGuid(){return'xxxxxxxxx-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);}); } (4认同)
  • @marc - Math.random()的质量是一个问题.但是如果没有详细分析底层实现,几乎肯定会改变x-browser,我们无法知道碰撞的实际几率.所以为了简单起见,我假设一个理想的随机源.但是,是的,这可能是一个危险的假设,因为muxa的问题凸显出来.这也是为什么在node-uuid(https://github.com/broofa/node-uuid/)中,我更喜欢其他API,它们保证了Math.random()的加密质量随机性,即使性能受到影响. (4认同)
  • 好吧,我的项目只是一个学校的多人网页游戏,所以没有人会因为碰撞而失去他们的钱或现实世界的身份.经过一夜的睡眠之后,我觉得自己过于偏执,考虑到有多么危险,但是当我需要客户端的随机数字时,我会始终记住这个警告. (4认同)
  • @DaveLong - `s/JSLint/JSHint /`应该解决这个问题.;)(但是,是的,`n | 0`是`Math.floor(n)`的简写,其中0 <= N <2 ^ 32) (4认同)
  • 对于任何一个"运算符'+'不能应用于类型'数字[]'和'-1000'"问题的人,请将此[1e7]用作任何+( - 1e3) (4认同)
  • crypto.randomUUID() 需要非常新的浏览器。https://caniuse.com/mdn-api_crypto_randomuuid。 (4认同)
  • @broofa:只要Math.random只产生伪随机数,你的赔率计算似乎是错误的:伪随机数是基于种子(以及已计算的伪随机数的数量),所以如果只有2 ^ x个不同的种子,则一个或多或少只会看到2 ^ x个不同的伪随机数,而不是2 ^ 122个.(也就是说,一个明确定义的可计算函数在N个不同的输入上进行求值时,最多只能产生N个不同的值.) (3认同)
  • 源字符串中的`y`和`4`有什么特别之处?为什么你不能在每个目标位置都有'x`? (3认同)
  • 我只是想知道`Math.random()*16 | 0`这一行是否与`Math.foor(Math.random()*16)`相同​​?管道没有正确使用JSLint,所以我只想重写一点. (3认同)
  • 如果您_真的_想要保持版本控制内联,而不是落后于修订历史记录,则必须颠倒顺序:首先保留最新的答案。 (3认同)
  • 这在 Typescript 中不起作用,它说无法添加“数字[]和数字” (3认同)
  • @DanRoss - 链接到这个答案很好.回复:"体面的随机数",这取决于你所说的"体面".Math.random()的主要问题是EcmaScript规范没有提供任何质量保证,只说random()使用"依赖于实现的算法或策略".因此,关于客户端UUID的任何讨论都包括关于随机数生成器质量的警告.:p (2认同)
  • 甚至可以进一步运行如下这样:` 'XXXXXXXX-XXXX-4XXX-YXXX-xxxxxxxxxxxx'.replace(/ [XY] /克,功能(C){风险R = 16*的Math.random()| 0;返回(' ?X'== C R:R&3 | 8)的ToString(16)});` (2认同)
  • 我回滚了添加使用`crypto`的实现的更新,因为这些实现要慢得多.这些实现及其优点应作为单独的答案添加,而不是在最高投票答案之上. (2认同)
  • 即使这个解决方案有可能发生碰撞,我也会说它足够了:) (2认同)
  • 我认为许多开发人员都陷入了困境。该代码必须是可读的,而不是单一代码。您是为其他开发人员而不是为计算机编写代码的,因此可读性(和可维护性)比紧凑性重要得多。如果您不使用变量(或者由于更复杂的问题而使用的函数/类),那么每个人都必须花费更多的时间来弄清楚代码的实际作用以及在代码损坏时如何对其进行修复,或者如何添加新的代码功能... (2认同)
  • 另一个TypeScript修复程序,更接近最初提出的逻辑:(''+ 1e7 + -1e3 + -4e3 + -8e3 + -1e11).replace(/ [018] / g,(c:any)=&gt;(c ^ crypto.getRandomValues(new Uint8Array(1))[0]&15 &gt;&gt; c / 4).t​​oString(16) (2认同)
  • 如果这个答案就像今天写的那样,而不是“更新”部分(这就是修订历史记录的用途),那就更好了。 (2认同)

Joh*_*kin 2225

根据RFC 4122,UUID(通用唯一标识符),也称为GUID(全局唯一标识符),是具有特定唯一性保证的标识符.

生成它们的最佳方法是遵循上述RFC中的实现指令,使用众多社区审查的开源实现之一,或者对于拥有它的语言,使用内置实现.

这里列出了一些用于处理UUID的开源工具,一些流行的编程语言.

JavaScript的

PHP

红宝石

蟒蛇


请注意,只是逐字节或逐字符地随机生成标识符,不会为符合要求的实现提供相同的保证.此外,非常重要的是,使用兼容UUID的系统可能选择不接受随机生成的系统,并且许多开源验证器实际上将检查有效的结构.

UUID必须具有以下格式:

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
Run Code Online (Sandbox Code Playgroud)

中号ñ位置可能只具有一定的价值.此时,M的唯一有效值是1,2,3,4和5,因此随机生成该位置将使大多数结果不可接受.

  • 实际上,RFC允许从随机数创建的UUID.你只需要旋转几个比特来识别它.见4.4节.从真正随机或伪随机数创建UUID的算法:http://www.rfc-archive.org/getrfc.php?rfc = 4122 (177认同)
  • 这不应该是公认的答案。它实际上并没有回答这个问题 - 相反,它鼓励导入 25,000 行代码,以实现在任何现代浏览器中只需一行代码即可完成的操作。 (53认同)
  • @Phil,这是一个“高度活跃的问题”,这意味着它应该有一个带有绿色勾号的出色答案。不幸的是事实并非如此。这个答案没有任何错误或不正确(如果有的话,我会编辑答案) - 但下面存在另一个更好的答案,我认为它应该位于列表的顶部。另外,这个问题特别与浏览器中的 javascript 有关,而不是与 Node.js 相关。 (4认同)
  • 我对 Math.random 的随机性质量如此之低的说法提出质疑。https://v8.dev/blog/math-random。正如您所看到的,它通过了良好的测试套件,并且 v8、FF 和 Safari 使用相同的算法。RFC 规定,UUID 可以接受伪随机数 (3认同)

Bri*_*y37 780

我真的很喜欢Broofa的答案是多么干净,但不幸的是,糟糕的实施Math.random会让碰撞机会失效.

这是一个类似的RFC4122版本4兼容解决方案,它通过将前13个十六进制数字偏移时间戳的十六进制部分来解决该问题.这样,即使Math.random是在同一个种子上,两个客户端都必须在完全相同的毫秒(或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())
Run Code Online (Sandbox Code Playgroud)


这是一个小小的测试.

  • [performance.now](https://github.com/daniellmb/perfnow.js)会更好.与Date.now不同,`performance.now()`返回的时间戳不限于1毫秒的分辨率.相反,它们表示时间为浮点数,精度高达**微秒**.与Date.now不同,performance.now()**返回的值总是以恒定速率**增加,与系统时钟无关,可以手动调整或由网络时间协议等软件偏移. (78认同)
  • 我认为这是最好的答案,因为它使用了它的生成日期.但是如果你有一个现代的浏览器堆栈我推荐`Date.now()`到`new Date().getTime()` (45认同)
  • 请记住,`new Date().getTime()`不会每毫秒更新一次.我不确定这会如何影响算法的预期随机性. (29认同)
  • 仅供参考,根据网站页脚,网站上的所有用户贡献均可通过cc by-sa 3.0许可证获得. (12认同)
  • @daniellmb你可能应该链接到MDN或其他人来显示真实的文档,而不是polyfill;) (6认同)
  • @NaveenReddyMarthala Node.js 默认情况下以严格模式运行 JavaScript,不幸的是,该模式不允许布尔逻辑运算符速记检查“未定义”变量的真实性。要解决此问题,请尝试将 var d2 = (performance ..` 替换为 var d2 = (typeof Performance !== 'undefined' ..` ,如更新版本中所示。另一个选项(实际上将利用Node.js 的性能而不是扔掉它)的方法是在您的需求中重新添加 `const { Performance } = require('perf_hooks');`。 (3认同)
  • 我可以知道d = Math.floor(d / 16);的使用舍入是什么吗? (2认同)
  • @Praveen该操作将时间戳向右移动一个十六进制数字并删除其余部分.它的目的是摆脱我们刚刚使用的十六进制数字(最不重要的数字),并为下一次迭代做好准备. (2认同)
  • @ nothing9:是的,根据4.4节中的[spec](http://www.ietf.org/rfc/rfc4122.txt),Y应该是10xx的形式,所以你是对的.感谢您指出这一点,答案现在已更新. (2认同)
  • @Megajin因为`Math.random`会产生一个介于0和1之间的数字,而忽略乘以16则意味着它不会改变结果。要查看此结果,请比较`(Math.random()%16)|的结果。0`与`(((Math.random()* 16)%16)| 0`。 (2认同)
  • 答案缺少解释'Math.random'可能很差的原因 (2认同)

Jef*_*ard 391

broofa的答案非常光滑,确实 - 令人印象深刻的聪明,真的... rfc4122兼容,有点可读,紧凑.真棒!

但是如果你正在查看那个正则表达式,那些很多replace()回调,函数toString()Math.random()函数调用(他只使用4位结果并浪费其余部分),你可能会开始怀疑性能.实际上,joelpt甚至决定抛弃RFC以获得通用的GUID速度generateQuickGUID.

但是,我们能否获得速度 RFC合规性?我说是! 我们能保持可读性吗?嗯...不是真的,但是如果你跟着它就很容易.

但首先,我的结果与broofa相比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.
Run Code Online (Sandbox Code Playgroud)

所以,我的优化迭代6日,我通过在击败了最流行的答案12X通过了,接受的答案9X,并通过快速不符合要求的答案,2-3X.我仍然符合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())
Run Code Online (Sandbox Code Playgroud)

所以,它取代x任何随机十六进制数字,y用随机数据(除了迫使前2位,以10每RFC规范),以及正则表达式不匹配-4人物,所以他没有来对付他们.非常非常光滑.

知道的第一件事是,函数调用是昂贵的,因为是正则表达式(虽然他只使用1,它有32个回调,一个每场比赛,并且在每个32个回调调用的Math.random()和v.的toString(16)).

性能的第一步是消除RegEx及其回调函数,而是使用简单的循环.这意味着我们必须处理-4字符,而broofa没有.另请注意,我们可以使用字符串数组索引来保持其光滑的字符串模板体系结构:

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())
Run Code Online (Sandbox Code Playgroud)

基本上,相同的内部逻辑,除了我们检查-4,并使用while循环(而不是replace()回调)使我们几乎提高了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())
Run Code Online (Sandbox Code Playgroud)

这节省了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())
Run Code Online (Sandbox Code Playgroud)

下一个优化是另一个经典.由于我们在每次循环迭代中只处理4位输出,所以让我们将循环次数减半,每次迭代处理8位.这很棘手,因为我们仍然需要处理符合RFC的位位置,但这并不难.然后我们必须制作一个更大的查找表(16x16或256)来存储0x00 - 0xff,我们只在e5()函数之外构建它一次.

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())
Run Code Online (Sandbox Code Playgroud)

我尝试了一次处理16位的e6(),仍然使用256个元素的LUT,它显示了优化的收益递减.尽管迭代次数较少,但内部逻辑由于处理增加而变得复杂,并且在桌面上执行相同,并且在移动设备上只有约10%的速度.

要应用的最终优化技术 - 展开循环.由于我们循环固定次数,我们可以在技术上手动写出这一切.我用一个随机变量r尝试了一次,我一直在重新分配,并且表现得很好.但是有四个变量预先分配随机数据,然后使用查找表,并应用适当的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())
Run Code Online (Sandbox Code Playgroud)

模块化:http://jcward.com/UUID.js -UUID.generate()

有趣的是,生成16字节的随机数据很容易.整个技巧是以符合RFC的字符串格式表达它,并且它使用16字节的随机数据,一个展开的循环和查找表来完成.

我希望我的逻辑是正确的 - 在这种繁琐的工作中犯错误很容易.但输出对我来说很好看.我希望你通过代码优化享受这种疯狂的旅程!

建议:我的主要目标是展示和教授潜在的优化策略.其他答案涵盖了重要的主题,如冲突和真正的随机数,这对于生成良好的UUID非常重要.

  • 这段代码仍然包含几个错误:`Math.random()*0xFFFFFFFF`行应该是`Math.random()*0x100000000`以获得完全随机性,并且应该使用`>>> 0`而不是`| 0 `保持值无符号(尽管使用当前代码,我认为即使它们已签名也可以正常运行).最后,如果可以的话,使用`window.crypto.getRandomValues`是一个非常好的主意,并且只有在绝对必要时才回退到Math.random.Math.random可能具有少于128位的熵,在这种情况下,这将比不必要的更容易受到冲突的影响. (11认同)
  • 我只能说——我已经数不清有多少次我向开发人员指出了这个答案,因为它如此完美地指出了性能、代码优雅性和可读性之间的权衡。谢谢杰夫。 (9认同)
  • 已经应用了@Dave的所有建议,并在这里发布了非常整洁的ES6/Babel源:http://codepen.io/avesus/pen/wgQmaV?edit = 0012 (7认同)
  • 我很想知道node-uuid.js是如何比较的.在我的工作中,我开始时更注重表现,其中一些仍然存在.但是我已经退出了,更喜欢具有更易读/可维护的代码.原因是uuid perf在现实世界中根本不是问题.Uuids通常与更慢的操作(例如,发出网络请求,创建和持久化模型对象)一起创建,其中刮掉几微秒的事情并不重要. (3认同)
  • 嗨@chad,好问题.k可以移到外面,但这并没有改善上面的性能并使范围变得更加混乱.建立一个阵列并加入回归奇怪地杀死了性能.但同样,请随意尝试! (2认同)

Kev*_*son 151

下面是基于一些代码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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我个人讨厌破折号,但是每个人都讨厌破碎.嘿,这就是为什么我们是程序员! (18认同)
  • @Levitikon .NET的`Guid.Parse()`应该将'B42A153F1D9A4F92990392C11DD684D2`解析为Guid就好了.它不需要连字符. (9认同)
  • 规范中的ABNF确实包含" - "字符,因此我更新为符合要求. (5认同)
  • 您应该事先声明数组大小,而不是在构建GUID时动态调整它的大小.`var s = new Array(36);` (4认同)
  • 这不会产生c#将其解析为System.Guid所需的破折号.它呈现如下:B42A153F1D9A4F92990392C11DD684D2,它应该呈现如下:B42A153F-1D9A-4F92-9903-92C11DD684D2 (3认同)
  • 我认为在设置clock_seq_hi_and_reserved的第6-7位为01的行中有一个非常小的错误。因为s[19]是一个字符'0'..'f'而不是一个int 0x0..0xf,(s [19] &amp; 0x3) | 0x8 不会随机分布——它会倾向于产生更多的“9”和更少的“b”。如果您出于某种原因关心随机分布,这只会有所不同。 (2认同)

Sim*_*gét 128

let uniqueId = Math.random().toString(36).substring(2) + Date.now().toString(36);
Run Code Online (Sandbox Code Playgroud)

document.getElementById("unique").innerHTML =
  Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36);
Run Code Online (Sandbox Code Playgroud)
<div id="unique">
</div>
Run Code Online (Sandbox Code Playgroud)

如果ID的生成间隔超过1毫秒,则它们是100%唯一的.

如果以较短的间隔生成两个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('-');
Run Code Online (Sandbox Code Playgroud)

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('-');
document.getElementById("unique").innerHTML = guid;
Run Code Online (Sandbox Code Playgroud)
<div id="unique">
</div>
Run Code Online (Sandbox Code Playgroud)

编辑:上面的代码遵循意图,但不是RFC的字母.在其他差异中,它是一些随机数字短.(如果需要,可以添加更多随机数字)优点是,与100%兼容的代码相比,这非常快.您可以在此处测试您的GUID

  • 这不是UUID吗? (4认同)
  • 在MAC地址上进行中继以在虚拟机上实现唯一性是一个坏主意! (4认同)
  • 对于那些想知道的人:`toString(36)` 转换为以 36 为基数的计数 (0..9a..z)。示例:“(35).toString(36)”是“z”。 (3认同)

Sla*_*ser 87

最快的GUID,如格式中的字符串生成器方法XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.这不会生成符合标准的GUID.

这个实现的1000万次执行只需要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();
}
Run Code Online (Sandbox Code Playgroud)

要测试性能,可以运行以下代码:

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

我相信大多数人都会明白我在那里做了什么,但也许至少有一个人需要解释:

算法:

  • Math.random()函数返回0到1之间的十进制数,小数点后的16位数(例如0.4363923368509859).
  • 然后我们取这个数字并将其转换为基数为16的字符串(从上面的示例中我们得到 0.6fb7687f).
    Math.random().toString(16).
  • 然后我们切断0.前缀(0.6fb7687f=> 6fb7687f)并得到一个长度为八个十六进制字符的字符串.
    (Math.random().toString(16).substr(2,8).
  • 有时Math.random()函数将返回较短的数字(例如0.4363),因为最后的零(从上面的例子,实际上是数字0.4363000000000000).这就是为什么我要附加到这个字符串"000000000"(一个包含九个零的字符串),然后用substr()函数将其剪掉,以使其准确地为九个字符(向右填充零).
  • 准确添加九个零的原因是因为更糟糕的情况,即Math.random()函数将正好返回0或1(每个单元的概率为1/10 ^ 16).这就是为什么我们需要向它添加九个零("0"+"000000000""1"+"000000000"),然后从长度为八个字符的第二个索引(第三个字符)中删除它.对于其他情况,添加零不会损害结果,因为它无论如何都会切断它.
    Math.random().toString(16)+"000000000").substr(2,8).

大会:

  • GUID采用以下格式XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.
  • 我将GUID分为4个部分,每个部分分为2种类型(或格式):XXXXXXXX-XXXX-XXXX.
  • 现在我正在构建使用这两种类型的GUID来组装带有调用4件的GUID,如下所示:XXXXXXXX -XXXX-XXXX -XXXX-XXXX XXXXXXXX.
  • 为了区分这两种类型,我在一个对创建器函数中添加了一个flag参数_p8(s),该s参数告诉函数是否添加破折号.
  • 最后我们使用以下链接构建GUID:_p8() + _p8(true) + _p8(true) + _p8()并返回它.

在我的博客上链接到这篇文章

请享用!:-)

  • 此实现不正确.GUID的某些字符需要特殊处理(例如,第13位需要是数字4). (13认同)
  • 不错的工作,但经典的优化技术使它快6倍(在我的浏览器上) - 见[我的回答](http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136) (3认同)

rip*_*234 62

以下是最高投票答案的组合,以及针对Chrome碰撞的解决方法:

generateGUID = (typeof(window.crypto) != 'undefined' && 
                typeof(window.crypto.getRandomValues) != 'undefined') ?
    function() {
        // If we have a cryptographically secure PRNG, use that
        // https://stackoverflow.com/questions/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
        // https://stackoverflow.com/questions/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);
        });
    };
Run Code Online (Sandbox Code Playgroud)

在jsbin上如果你想测试它.

  • 请注意,第一个版本,一个`window.crypto.getRandomValues`,不保留RFC 4122定义的版本4 UUID格式.而不是`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`它产生`xxxxxxxx-xxxx -xxxx-XXXX-xxxxxxxxxxxx`. (3认同)
  • 我相信在IE中它实际上是window.msCrypto而不是window.crypto.可能很高兴检查两者.请参阅http://msdn.microsoft.com/en-us/library/ie/dn265046(v=vs.85).aspx (2认同)

joe*_*lpt 60

这是一个完全不兼容但非常高性能的实现,用于生成类似于ASCII的GUID类唯一标识符.

function generateQuickGuid() {
    return Math.random().toString(36).substring(2, 15) +
        Math.random().toString(36).substring(2, 15);
}
Run Code Online (Sandbox Code Playgroud)

生成26个[a-z0-9]字符,产生的UID比RFC兼容的GUID更短且更独特.如果人类可读性很重要,可以简单地添加破折号.

以下是此功能的使用示例和时间以及此问题的其他几个答案.计时在Chrome m25下进行,每次迭代1000万次.

>>> 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
Run Code Online (Sandbox Code Playgroud)

这是时间码.

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


Jed*_*idt 58

以下是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)}
Run Code Online (Sandbox Code Playgroud)

这实现了与当前评分最高的答案相同的目标,但是通过利用强制,递归和指数表示法减少了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
      )
}
Run Code Online (Sandbox Code Playgroud)

  • 在TypeScript中使用以下命令:`export const UUID = function b(a:number):string {return a?(a ^ Math.random()* 16 &gt;&gt; a / 4).t​​oString(16):(''+ [1e7] +-1e3 + -4e3 + -8e3 + -1e11).replace(/ [018] / g,b )};` (2认同)

Pre*_*aul 43

来自sagi 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;
}
Run Code Online (Sandbox Code Playgroud)

还有其他方法涉及使用ActiveX控件,但远离这些!

编辑: 我认为值得指出的是没有GUID生成器可以保证唯一键(查看维基百科文章).始终存在碰撞的可能性.GUID只提供足够大的键,以将碰撞的变化减少到几乎为零.

  • 请注意,这不是技术意义上的GUID,因为它不会保证唯一性.根据您的申请,这可能或不重要. (8认同)
  • 没有GUID保证是唯一的......创建的密钥的范围非常大,足以使碰撞几乎不可能. (8认同)
  • 关于性能的快速说明.此解决方案共创建36个字符串以获得单个结果.如果性能至关重要,请考虑创建阵列并按照以下建议加入:http://tinyurl.com/y37xtx进一步研究表明它可能无关紧要,因此YMMV:http://tinyurl.com/3l7945 (2认同)
  • 关于唯一性,值得注意的是,版本1,3和5 UUID是版本4所没有的确定性。如果这些uuid生成器的输入(v1中的节点ID,v3和v5中的名称空间和名称)是唯一的(应该是这样),那么生成的UUID就是唯一的。从理论上讲。 (2认同)

小智 39

你可以使用node-uuid(https://github.com/kelektiv/node-uuid)

简单,快速生成RFC4122 UUIDS.

特征:

  • 生成RFC4122版本1或版本4 UUID
  • 在node.js和浏览器中运行.
  • 密码学上强大的随机#生成在支持平台上.
  • 占地面积小(想要更小的东西吗?看看这个!)

使用NPM安装:

npm install uuid
Run Code Online (Sandbox Code Playgroud)

或者通过浏览器使用uuid:

下载原始文件(uuid v1):https://raw.githubusercontent.com/kelektiv/node-uuid/master/v1.js 下载原始文件(uuid v4):https://raw.githubusercontent.com/kelektiv/node -uuid /主/ 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'
Run Code Online (Sandbox Code Playgroud)

ES6:

import uuid from 'uuid/v4';
const id = uuid();
Run Code Online (Sandbox Code Playgroud)

  • **注意:** 这些导入对我不起作用。导入语句已更改,如存储库中所述:`const { v4: uuidv4 } = require('uuid');` 和 ES6:`import { v4 as uuidv4 } from 'uuid';` (2认同)

Pie*_*eau 32

新增:v15.6.0、v14.17.0 内置crypto.randomUUID()函数。

import { randomUUID } from "node:crypto";

const uuid = crypto.randomUUID();
Run Code Online (Sandbox Code Playgroud)

在浏览器中,crypto.randomUUID()目前在 Chromium 92+ 和 Firefox 95+ 中受支持。


Sea*_*ean 31

Web服务很有用.

快速谷歌发现:http://www.hoskinson.net/GuidGenerator/

无法担保此实现,但SOMEONE必须发布一个真正的GUID生成器.

使用这样的Web服务,您可以开发一个使用GUID Web服务的REST Web界面,并通过AJAX在浏览器中将其提供给javascript.

  • 我制作,托管并使用了这个:http://www.timjeanes.com/guid.它使用.NET生成一个新的GUID并返回它而不会有任何额外的毛病.它也适用于JSONP. (10认同)
  • 一个提供GUID的Web服务,真的吗?这几乎和编写Web服务以提供随机数一样奇怪 - 除非您需要真正随机数字由连接到服务器的某些物理噪声源生成,即. (9认同)

sle*_*erd 31

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);
    });
};
Run Code Online (Sandbox Code Playgroud)

编辑:

重新审视了我正在使用此功能并且不喜欢详细程度的项目. - 但需要适当的随机性.

一个基于Briguy37答案的版本和一些按位运算符从缓冲区中提取半字节大小的窗口.

应该遵循RFC Type 4(随机)模式,因为我上次使用Java的UUID解析不合规的uuids时出现问题.


kay*_*yz1 29

简单的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());
Run Code Online (Sandbox Code Playgroud)

用法:

Guid.newGuid()

"c6c2d12f-d76b-5739-e551-07e6de5b0807"

Guid.empty

"00000000-0000-0000-0000-000000000000"

  • `_cryptoGuid`不应该在第3部分的开头包含一个'4',如`_guid`吗? (2认同)

jve*_*ema 25

嗯,这已经有了很多答案,但不幸的是,这一堆中没有"​​真正的"随机.下面的版本是对broofa答案的改编,但更新后包含一个"真正的"随机函数,它在可用时使用加密库,而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);
  });
};
Run Code Online (Sandbox Code Playgroud)


Mat*_*agé 24

这创建版本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('');
}
Run Code Online (Sandbox Code Playgroud)

以下是生成的UUID示例:

682db637-0f31-4847-9cdf-25ba9613a75c
97d19478-3ab2-4aa1-b8cc-a1c3540f54aa
2eed04c9-2692-456d-a0fd-51012f947136
Run Code Online (Sandbox Code Playgroud)


Woj*_*ski 24

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的低时间戳分辨率由随机数补偿.


小智 17

  // 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('-');
Run Code Online (Sandbox Code Playgroud)


Tra*_*er1 14

调整与一些额外的我自己的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));
Run Code Online (Sandbox Code Playgroud)


And*_*rew 14

我想了解broofa的答案,所以我扩展了它并添加了评论:

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);
        }
    );
};
Run Code Online (Sandbox Code Playgroud)


Ara*_*oca 13

本机URL.createObjectURL正在生成一个 UUID。你可以利用这一点。

function uuid() {
  const url = URL.createObjectURL(new Blob())
  const [id] = url.toString().split('/').reverse()
  URL.revokeObjectURL(url)
  return id
}
Run Code Online (Sandbox Code Playgroud)


Joh*_*ler 12

对于那些想要符合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() );
Run Code Online (Sandbox Code Playgroud)

上述功能应该在速度和随机性之间保持适当的平衡.


Beh*_*adi 12

ES6样本

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


ale*_*kop 11

这只是一个简单的AJAX调用......

如果有人仍然感兴趣,这是我的解决方案.

在服务器端:

[WebMethod()]
public static string GenerateGuid()
{
    return Guid.NewGuid().ToString();
}
Run Code Online (Sandbox Code Playgroud)

在客户端:

var myNewGuid = null;
PageMethods.GenerateGuid(
    function(result, userContext, methodName)
    {
        myNewGuid = result;
    },
    function()
    {
        alert("WebService call failed.");
    }
);
Run Code Online (Sandbox Code Playgroud)

  • 如果使用ASP.NET,为什么需要进行AJAX调用?只需在aspx中执行<%= Guid.NewGuid().ToString()%>. (10认同)
  • @ kape123:如果你只想要一个GUID,那很好.Web服务允许您生成多个GUID而无需重新加载页面. (3认同)
  • 你是对的,异步调用这不是很有用.具有讽刺意味的是,我的原始代码确实使用jQuery同步调用此方法.这是一个例子:$ .ajax({async:false,type:'POST',url:'MyPage.aspx/GenerateGuid',contentType:'application/json; charset = utf-8',data:'{}', success:function(data){// data包含你的新GUID},失败:function(msg){alert(msg);}}); (2认同)

And*_*rri 11

更好的方法:

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
 }
Run Code Online (Sandbox Code Playgroud)

最小化:

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}
Run Code Online (Sandbox Code Playgroud)

  • 为什么更好? (2认同)

lin*_*ing 10

这个基于日期,并添加随机后缀以"确保"唯一性.适用于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;
        };
Run Code Online (Sandbox Code Playgroud)


Jon*_*ter 10

如果您只需要一个无特殊格式的随机128位字符串,您可以使用:

function uuid() {
    return crypto.getRandomValues(new Uint32Array(4)).join('-');
}
Run Code Online (Sandbox Code Playgroud)

这将返回类似的东西2350143528-4164020887-938913176-2513998651.

  • 您还可以添加这样的字符(字母):`Array.from((window.crypto || window.msCrypto).getRandomValues(new Uint32Array(4))).map(n =&gt; n.toString(16)).加入('-')` (2认同)

Lev*_*kon 9

有一个jQuery插件可以很好地处理Guid的http://plugins.jquery.com/project/GUID_Helper

jQuery.Guid.Value()
Run Code Online (Sandbox Code Playgroud)

返回内部Guid的值.如果未指定guid,则返回一个新值(然后在内部存储值).


jQuery.Guid.New()
Run Code Online (Sandbox Code Playgroud)

返回一个新的Guid并在内部设置它的值.


jQuery.Guid.Empty()
Run Code Online (Sandbox Code Playgroud)

返回空Guid 00000000-0000-0000-0000-000000000000.


jQuery.Guid.IsEmpty()
Run Code Online (Sandbox Code Playgroud)

返回布尔值.如果为空/未定义/空/空,则为真.


jQuery.Guid.IsValid()
Run Code Online (Sandbox Code Playgroud)

返回布尔值.真正有效的guid,如果不是,则为false.


jQuery.Guid.Set()
Run Code Online (Sandbox Code Playgroud)

Retrns Guid.将Guid设置为用户指定的Guid,如果无效,则返回空guid.

  • 插件链接已损坏 (2认同)

Ana*_*nov 9

我知道,这是一个老问题.为了完整起见,如果您的环境是SharePoint,则会有一个名为SP.Guid.newGuid(msdn link)的实用程序函数,它会创建一个新的guid.此函数位于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;
};
Run Code Online (Sandbox Code Playgroud)


rob*_*cat 9

crypto.getRandomValues(a)支持的浏览器(IE11 +,iOS7 +,FF21 +,Chrome,Android Chrome)上使用的简单代码.避免使用Math.random(),因为这可能会导致碰撞(例如碰撞20 4000生成的UUID在由真实情况MUXA).

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);
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 优化代码可读性而不是速度,所以适合说几百uuid每秒.使用http://jsbin.com/fuwigo/1测量性能,在我的笔记本电脑上每秒在Chromium中生成大约10000 uuid().
  • 仅对"y"使用8,因为这简化了代码可读性(y允许为8,9,A或B).


Ali*_*eza 9

好的,使用uuid包及其对版本 1、3、4 和 5 UUID 的支持,请执行以下操作:

yarn add uuid
Run Code Online (Sandbox Code Playgroud)

进而:

const uuidv1 = require('uuid/v1');
uuidv1(); // ? '45745c60-7b1a-11e8-9c9c-2d42b21b1a3e'
Run Code Online (Sandbox Code Playgroud)

您还可以使用完全指定的选项来执行此操作:

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'
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请访问此处的 npm 页面。


amn*_*amn 8

我找不到任何使用单个 16 个八位字节TypedArray和 a 的答案DataView,因此我认为以下用于根据 RFC生成版本 4 UUID 的解决方案将在此处独立存在:

function uuid4() {
    const ho = (n, p) => n.toString(16).padStart(p, 0); /// Return the hexadecimal text representation of number `n`, padded with zeroes to be of length `p`
    const view = new DataView(new ArrayBuffer(16)); /// Create a view backed by a 16-byte buffer
    crypto.getRandomValues(new Uint8Array(view.buffer)); /// Fill the buffer with random data
    view.setUint8(6, (view.getUint8(6) & 0xf) | 0x40); /// Patch the 6th byte to reflect a version 4 UUID
    view.setUint8(8, (view.getUint8(8) & 0x3f) | 0x80); /// Patch the 8th byte to reflect a variant 1 UUID (version 4 UUIDs are)
    return `${ho(view.getUint32(0), 8)}-${ho(view.getUint16(4), 4)}-${ho(view.getUint16(6), 4)}-${ho(view.getUint16(8), 4)}-${ho(view.getUint32(10), 8)}${ho(view.getUint16(14), 4)}`; /// Compile the canonical textual form from the array data
}
Run Code Online (Sandbox Code Playgroud)

我更喜欢它,因为它只依赖于标准 ECMAScript 平台可用的函数,在可能的情况下——这只是一个过程(下面描述的那个)。

请注意,在撰写本文时,Node.js 中getRandomValuescrypto对象尚未实现。但是,它具有randomBytes可以替代的等效功能。


cev*_*ing 7

只是另一个具有两个突变的可读变体.

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, '-');
}
Run Code Online (Sandbox Code Playgroud)


dge*_*low 7

broofa 2017-06-28 更新的 TypeScript 版本,基于cryptoAPI:

function genUUID() {
    // Reference: /sf/answers/148226641/
    return ("10000000-1000-4000-8000-100000000000").replace(/[018]/g, s => {
        const c = Number.parseInt(s, 10)
        return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
    })
}
Run Code Online (Sandbox Code Playgroud)

理由:

  • 使用+Betweennumber[]number无效
  • string从到 的转换number必须是显式的


Tik*_*olu 7

使用 Blob 的单行解决方案。

window.URL.createObjectURL(new Blob([])).substring(31);
Run Code Online (Sandbox Code Playgroud)

末尾的值 (31) 取决于 URL 的长度。

  • 或者 `window.URL.createObjectURL(new Blob([])).split('/').pop()` 将执行相同的操作,而不必依赖 URL 长度等外部因素。 (6认同)
  • 什么是“斑点”/“斑点”? (2认同)
  • 最好在紧凑的解决方案中用 slice 替换 substr 。`URL.createObjectURL(new Blob([])).slice(-36)` (2认同)

ska*_*lee 6

这里有很多正确的答案,但遗憾的是,包含的代码示例非常神秘且难以理解。这就是我创建版本 4(随机)UUID 的方法。

请注意,以下代码片段使用二进制文字来提高可读性,因此需要 ECMAScript 6。

Node.js 版本

function uuid4() {
  let array = new Uint8Array(16)
  crypto.randomFillSync(array)

  // Manipulate the 9th byte
  array[8] &= 0b00111111 // Clear the first two bits
  array[8] |= 0b10000000 // Set the first two bits to 10

  // Manipulate the 7th byte
  array[6] &= 0b00001111 // Clear the first four bits
  array[6] |= 0b01000000 // Set the first four bits to 0100

  const pattern = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  let idx = 0

  return pattern.replace(
    /XX/g,
    () => array[idx++].toString(16).padStart(2, "0"), // padStart ensures a leading zero, if needed
  )
}
Run Code Online (Sandbox Code Playgroud)

浏览器版本

只有第二行不同。

function uuid4() {
  let array = new Uint8Array(16)
  crypto.getRandomValues(array)

  // Manipulate the 9th byte
  array[8] &= 0b00111111 // Clear the first two bits
  array[8] |= 0b10000000 // Set the first two bits to 10

  // Manipulate the 7th byte
  array[6] &= 0b00001111 // Clear the first four bits
  array[6] |= 0b01000000 // Set the first four bits to 0100

  const pattern = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  let idx = 0

  return pattern.replace(
    /XX/g,
    () => array[idx++].toString(16).padStart(2, "0"), // padStart ensures a leading zero, if needed
  )
}
Run Code Online (Sandbox Code Playgroud)

测试

最后,相应的测试(Jasmine)。

describe(".uuid4()", function() {
  it("returns a UUIDv4 string", function() {
    const uuidPattern = "XXXXXXXX-XXXX-4XXX-YXXX-XXXXXXXXXXXX"
    const uuidPatternRx = new RegExp(uuidPattern.
      replaceAll("X", "[0-9a-f]").
      replaceAll("Y", "[89ab]"))

    for (let attempt = 0; attempt < 1000; attempt++) {
      let retval = uuid4()
      expect(retval.length).toEqual(36)
      expect(retval).toMatch(uuidPatternRx)
    }
  })
})
Run Code Online (Sandbox Code Playgroud)

UUID v4 解释

关于 UUID 版本 4 的一个很好的解释是:Generate a UUID compliant with RFC 4122

最后的笔记

此外,还有很多第三方软件包。不过,只要你只有基本需求,我就不推荐它们。确实,赢的不多,输的也很多。作者可能会追求最微小的性能,“修复”不应该修复的东西,而当涉及到安全性时,这是一个冒险的想法。同样,它们可能会引入其他错误或不兼容性。仔细更新需要时间。


blu*_*lub 6

受到broofa 回答的启发,我有自己的看法:

这是使用crypto.getRandomValues.

function uuidv4() {
    const a = crypto.getRandomValues(new Uint16Array(8));
    let i = 0;
    return '00-0-4-1-000'.replace(/[^-]/g, 
            s => (a[i++] + s * 0x10000 >> s).toString(16).padStart(4, '0')
    );
}

console.log(uuidv4());
Run Code Online (Sandbox Code Playgroud)

这是Math.random使用几乎相同原理的更快版本:

function uuidv4() {
    return '00-0-4-1-000'.replace(/[^-]/g,
            s => ((Math.random() + ~~s) * 0x10000 >> s).toString(16).padStart(4, '0')
    );
}

console.log(uuidv4());
Run Code Online (Sandbox Code Playgroud)


Shi*_*hah 5

重要的是要使用由超过1个贡献者维护的经过良好测试的代码,而不是为此自己动手.这是你可能希望最喜欢最稳定的代码的地方之一,而不是在X浏览器中工作的最短的聪明版本,但不考虑Y的特性,这通常会导致非常难以调查错误,而不仅仅是随机显示对于一些用户.我个人在https://github.com/aurigadl/uuid-js上使用了uuid-js,它启用了bower,因此我可以轻松获取更新.


小智 5

我正在使用以下功能:

function NewGuid()
{
    var sGuid = "";
    for (var i=0; i<32; i++)
    {
        sGuid += Math.floor(Math.random()*0xF).toString(0xF);
    }
    return sGuid;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

生成唯一标识的一个简单解决方案是使用时间令牌并向其添加随机数。我更喜欢在它前面加上“uuid-”前缀。

以下函数将生成类型为:uuid-14d93eb1b9b4533e6的随机字符串。不需要生成 32 个字符的随机字符串。在这种情况下,16 个字符的随机字符串足以在 JavaScript 中提供唯一的 UUID。

var createUUID = function() {
  return "uuid-" + ((new Date).getTime().toString(16) + Math.floor(1E7*Math.random()).toString(16));
}
Run Code Online (Sandbox Code Playgroud)


and*_*rsh 5

你可以使用 npm 包guid,一个 GUID 生成器和验证器。

例子:

Guid.raw();
// -> '6fdf6ffc-ed77-94fa-407e-a7b86ed9e59d'
Run Code Online (Sandbox Code Playgroud)

注意:此包已被弃用。请改用uuid

例子:

const uuidv4 = require('uuid/v4');
uuidv4(); // ? '10ba038e-48da-487b-96e8-8d3b99b6d18a'
Run Code Online (Sandbox Code Playgroud)


小智 5

这也适用于 Node.js,如果你替换let buffer = new Uint8Array(); crypto.getRandomValueslet buffer = crypto.randomBytes(16)

它应该在性能上击败大多数正则表达式解决方案。

const hex = '0123456789ABCDEF'

let generateToken = function() {
    let buffer = new Uint8Array(16)

    crypto.getRandomValues(buffer)

    buffer[6] = 0x40 | (buffer[6] & 0xF)
    buffer[8] = 0x80 | (buffer[8] & 0xF)

    let segments = []

    for (let i = 0; i < 16; ++i) {
        segments.push(hex[(buffer[i] >> 4 & 0xF)])
        segments.push(hex[(buffer[i] >> 0 & 0xF)])

        if (i == 3 || i == 5 || i == 7 || i == 9) {
            segments.push('-')
        }
    }

    return segments.join('')
}

for (let i = 0; i < 100; ++i) {
  console.log(generateToken())
}
Run Code Online (Sandbox Code Playgroud)

性能图表(每个人都喜欢它们):jsbench


Fer*_*les 5

执行此操作的最简单功能:

function createGuid(){  
   let S4 = () => Math.floor((1+Math.random())*0x10000).toString(16).substring(1); 
   let guid = `${S4()}${S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}`;
   
   return guid.toLowerCase();  
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这是什么样子

let uuid = function(){
     return Array
      .from(Array(16))
      .map(e => Math.floor(Math.random() * 255)
      .toString(16)
      .padStart(2,"0"))
      .join('')
      .match(/.{1,4}/g)
      .join('-')
}

console.log(uuid())
console.log(uuid())
Run Code Online (Sandbox Code Playgroud)