题 在JavaScript中创建GUID / UUID?


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

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


3219


起源


GUIDs作为字符串被重复时至少为36个字符且长度不超过38个字符并且匹配模式^ \ {?[a-zA-Z0-9] {36}?\} $因此总是ascii。 - AnthonyWJones
David Bau提供了一个更好,可播种的随机数生成器 davidbau.com/archives/2010/01/30/... 我写了一个稍微不同的方法来生成UUID blogs.cozi.com/tech/2010/04/generating-uuids-in-javascript.html - George V. Reilly
jsben.ch/#/Lbxoe  - 这里是以下不同功能的基准 - EscapeNetscape
UUID随机 使用良好的PRNG并且非常快。 - jchook
迟到(很晚!)来到这里的聚会,但@AnthonyWJones不应该你的正则表达式读取:^ \ {?[a-fA-F0-9] {36}?\} $ - noonand


答案:


在这方面有几次尝试。问题是:你想要实际的GUID,还是只需要随机数  像GUIDs?生成随机数很容易。

function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}

但是,请注意这样的值 不是真正的GUID

无法在Javascript中生成真正的GUID,因为它们依赖于浏览器不公开的本地计算机的属性。您需要使用ActiveX等特定于操作系统的服务: http://p2p.wrox.com/topicindex/20339.htm

编辑:不正确 - RFC4122允许随机(“版本4”)GUID。有关细节,请参阅其他答案。

注意:提供的代码段不遵循需要该版本的RFC4122(4)必须集成到生成的输出字符串中。 不要使用这个答案 如果您需要兼容的GUID。

使用:

var uuid = guid();

演示:

function guid() {
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
}

function s4() {
  return Math.floor((1 + Math.random()) * 0x10000)
    .toString(16)
    .substring(1);
}

document.getElementById('jsGenId').addEventListener('click', function() {
  document.getElementById('jsIdResult').value = guid();
})
input { font-family: monospace; }
<button id="jsGenId" type="button">Generate GUID</button>
<br>
<input id="jsIdResult" type="text" placeholder="Results will be placed here..." readonly size="40"/>


1904



实际上,RFC允许从随机数创建的UUID。你只需要旋转几个比特来识别它。见4.4节。从真正的随机数或伪随机数创建UUID的算法: rfc-archive.org/getrfc.php?rfc=4122 - Jason DeFontes
有人可以向我解释这段代码吗?看起来S4函数试图在0x10000和0x20000之间获得一个随机十六进制数,然后输出最后4位数。但为什么按位或0?不应该是noop?还有,0x10000到0x20000只是一个黑客,以避免不得不处理领先的0? - Cory
在Chrome中,此代码并不总是生成正确大小的GUID。长度在35到36之间 - cdeutsch
一个如此明显错误的答案怎么能得到这么多的赞成?即使代码是错误的,因为在正确的位置没有4。 en.wikipedia.org/wiki/Globally_unique_identifier - Dennis Krøger
当删除“1 + ....”和“substring(1)”时,在修订版5中打破了这个答案。这些位保证了一致的长度。 - Segfault


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())

更新,2015-06-02:请注意,UUID唯一性在很大程度上依赖于底层随机数生成器(RNG)。上面的解决方案使用 Math.random() 但是为了简洁起见 Math.random() 是  保证是高品质的RNG。见亚当海兰德 Math.random上的优秀写作() 详情。对于更强大的解决方案,请考虑类似的问题 uuid模块[免责声明:我是作者],它使用更高质量的RNG API。

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

更新,2017-06-28: 一个 来自Chrome开发人员的好文章 讨论Chrome,Firefox和Safari中Math.random PRNG质量的状态。 tl; dr - 截至2015年底,它“非常好”,但不是加密质量。为了解决这个问题,这里是使用ES6的上述解决方案的更新版本 crypto API,和 有点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());


3150



使用此代码在客户端上生成唯一ID,然后使用这些ID作为主键来保存服务器上的对象是否安全? - Muxa
...(续)此功能碰撞产生的两个ID的几率在字面上是天文数字小。 ID的128位中除了6位之外的所有ID都是随机生成的,这意味着对于任何两个ID,它们将发生碰撞的概率为1 ^ 2 ^^ 122(或5.3x10 ^^ 36)。 - broofa
我发布了一个关于碰撞的问题 stackoverflow.com/questions/6906916/... - Muxa
当然,@ Muxa问题的答案是'不'?信任来自客户的东西绝不是真正安全的。我想这取决于你的用户提出一个javascript控制台的可能性,并手动将变量更改为他们想要的东西。或者他们可以给你发回他们想要的id。这还取决于用户选择自己的ID是否会导致漏洞。无论哪种方式,如果它是一个随机数字ID进入一个表,我可能会生成它在服务器端,所以我知道我可以控制该过程。 - Cam Jackson
@DrewNoakes - UUID不只是一串完全随机的#。 “4”是uuid版本(4 =“随机”)。 “y”标记需要嵌入uuid变体(基本上是字段布局)的位置。见第4.1.1和4.1.3节 ietf.org/rfc/rfc4122.txt 了解更多信息。 - broofa


我真的很喜欢干净 Broofa的回答 是,但不幸的是,糟糕的实施 Math.random 留下碰撞的机会。

这是一个类似的 RFC4122 符合版本4的解决方案,通过将前13个十六进制数字偏移时间戳的十六进制部分来解决该问题。就这样,即使 Math.random在同一种子上,两个客户端都必须在完全相同的毫秒(或10,000多年后)生成UUID才能获得相同的UUID:

function generateUUID() { // Public Domain/MIT
    var d = new Date().getTime();
    if (typeof performance !== 'undefined' && typeof performance.now === 'function'){
        d += performance.now(); //use high-precision timer if available
    }
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = (d + Math.random() * 16) % 16 | 0;
        d = Math.floor(d / 16);
        return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
    });
}


这是一个小小的测试。


672



记住, new Date().getTime() 没有每毫秒更新一次。我不确定这会如何影响算法的预期随机性。 - devios1
我认为这是最好的答案,因为它使用了它的生成日期。但是,如果你有一个现代的浏览器堆栈,我建议 Date.now() 至 new Date().getTime() - Fresheyeball
performance.now 会更好。与Date.now不同,返回的时间戳由 performance.now() 不限于一毫秒的分辨率。相反,它们表示时间为浮点数,最多为 微秒精度。与Date.now不同,performance.now()返回的值 总是以恒定的速度增加,与系统时钟无关,可以手动调整,也可以通过网络时间协议等软件进行调整。 - daniellmb
@daniellmb你可能应该链接到MDN或其他人来显示真实的文档,而不是polyfill;) - Martin
仅供参考,根据网站页脚,网站上的所有用户贡献均可通过cc by-sa 3.0许可证获得。 - Xiong Chiamiov


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.

因此,通过我的第6次优化迭代,我击败了最受欢迎的答案 12X,接受的答案 9X,以及快速不合规的答案 2-3X。我仍然符合rfc4122标准。

对如何感兴趣?我把完整的资源放在了 http://jsfiddle.net/jcward/7hyaC/3/ 并且 http://jsperf.com/uuid-generator-opt/4

要解释一下,让我们从broofa的代码开始:

'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);
});

所以它取而代之 x 任何随机的十六进制数字, y 随机数据(除了强制前2位) 10 根据RFC规范),正则表达式与 - 要么 4 人物,所以他没有必要处理它们。非常非常光滑。

首先要知道的是函数调用是很昂贵的,正则表达式也是如此(尽管他只使用1,它有32个回调,每个匹配一个,并且在32个回调中的每个回调中都调用Math.random()和v。的toString(16))。

性能的第一步是消除RegEx及其回调函数,而是使用简单的循环。这意味着我们必须处理 - 和 4 人物,而布洛法没有。另外,请注意我们可以使用String Array索引来保持其光滑的String模板体系结构:

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;
}

基本上,相同的内在逻辑,除了我们检查 - 要么 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
}

这节省了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
}

下一个优化是另一个经典。由于我们在每次循环迭代中只处理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
}

我尝试了一次处理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];
}

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

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

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

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


308



jsperf.com 允许您捕获数据并查看跨浏览器和设备的结果。 - fearphage
嗨@chad,好问题。 k可以移到外面,但这并没有改善上面的性能并使范围变得更加混乱。建立一个阵列并加入回归奇怪地杀死了性能。但同样,请随意尝试! - Jeff Ward
我很想知道node-uuid.js是如何比较的。在我的工作中,我开始时更多地关注性能,其中一些仍然存在。但是我已经退出了,更喜欢拥有更易读/可维护的代码。原因是uuid perf在现实世界中根本不是问题。 Uuids通常与更慢的操作(例如,制作网络请求,创建和持久化模型对象)一起创建,其中刮掉几微秒的事物并不重要。 - broofa
此代码仍包含几个错误: Math.random()*0xFFFFFFFF 线应该是 Math.random()*0x100000000 完全随机,和 >>>0 应该用来代替 |0 保持值无符号(虽然使用当前代码我认为即使它们已签名也可以正常运行)。最后,这些天使用它将是一个非常好的主意 window.crypto.getRandomValues 如果可用,则仅在绝对必要时才回退到Math.random。 Math.random可能具有少于128位的熵,在这种情况下,这将比不必要的更容易受到冲突的影响。 - Dave
已经应用了@Dave的所有建议,并在这里发布了非常简洁的ES6 / Babel源: codepen.io/avesus/pen/wgQmaV?editors=0012 - Brian Haak


这是基于的一些代码 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;
}

138



这不会产生c#将其解析为System.Guid所需的破折号。它呈现如下:B42A153F1D9A4F92990392C11DD684D2,它应该呈现为:B42A153F-1D9A-4F92-9903-92C11DD684D2 - Levitikon
规范中的ABNF确实包含“ - ”字符,因此我更新为符合要求。 - Kevin Hakanson
我个人讨厌破折号,但是每个人都讨厌破碎。嘿,这就是为什么我们是程序员! - devios1
您应该事先声明数组大小,而不是在构建GUID时动态调整它的大小。 var s = new Array(36); - MgSam
@Levitikon .NET Guid.Parse() 应该解析 B42A153F1D9A4F92990392C11DD684D2 进入Guid就好了。它不需要连字符。 - JLRishe


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

这个实现的一千万次执行只需要32.5秒,这是我在浏览器中见过的最快的(没有循环/迭代的唯一解决方案)。

功能如下:

/**
 * Generates a GUID string.
 * @returns {String} The generated GUID.
 * @example af8a8416-6e18-a307-bd9c-f2c947bbb3aa
 * @author Slavik Meltser (slavik@meltser.info).
 * @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');

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

算法:

  • Math.random() 函数返回0到1之间的十进制数,小数点后的16位数(for 例 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"),然后从长度为8个字符的第二个索引(第3个字符)中删除它。对于其他情况,添加零不会损害结果,因为它无论如何都会切断它。
    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(),并返回它。

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

请享用! :-)


79



此实现不正确。 GUID的某些字符需要特殊处理(例如,第13位需要是数字4)。 - JLRishe
@JLRishe,你是对的,它没有遵循RFC4122标准。但它仍然是一个看起来像GUID的随机字符串。干杯:-) - Slavik Meltser
不错的工作,但经典的优化技术使它快6倍(在我的浏览器上) - 请参阅 我的答案 - Jeff Ward


var uniqueId = Math.random().toString(36).substring(2) 
               + (new Date()).getTime().toString(36);

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

如果以较短的间隔生成两个ID,并且假设随机方法是真正随机的,那么这将产生99.99999999999999%可能是全局唯一的ID(在10 ^ 15中的1中发生冲突)

您可以通过添加更多数字来增加此数字,但要生成100%唯一ID,您需要使用全局计数器。

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


69



这不是UUID吗? - Marco Kerwitz
No.UUID / GUID是122位(+6保留位)编号。它可以通过全球计数器服务保证唯一性,但通常会按时,MAC地址和随机性进行中继。 UUID不是随机的!我在这里建议的UID没有完全压缩。您可以将其压缩为122位整数,添加6个预定义位和额外的随机位(删除一些计时器位),最后得到一个完美形成的UUID / GUID,然后您必须转换为十六进制。对我而言,除了符合ID的长度之外,并没有真正添加任何其他内容。 - Simon Rigét
在虚拟机上传递唯一性的MAC地址是一个坏主意! - Simon Rigét


这是一个组合 最高投票的答案,解决方法 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);
        });
    };

在jsbin上 如果你想测试它。


57



我相信在IE中它实际上是window.msCrypto而不是window.crypto。可能很高兴检查两者。看到 msdn.microsoft.com/en-us/library/ie/dn265046(v=vs.85).aspx - herbrandson
注意第一个版本,一个是`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