如何在JavaScript中创建GUID(全球独特识别器)?GUID/UUID应该至少有32个字符,并且应该保持在ASCII范围内,以避免在通过它们时遇到麻烦。

我不确定在所有浏览器上有哪些习惯,如何“随机”和种植内置的随机号码发电机等。


当前回答

基于加密 API 的 2017-06-28 的 Broofa 的 TypeScript 版本:

function genUUID() {
    // Reference: https://stackoverflow.com/a/2117523/709884
    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)
    })
}

原因:

使用 + 之间的数字( )和数字不有效 从行到数字的转换必须是明确的

其他回答

最好的方式:

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,
                  ?              // generate 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}

最简单的功能来做到这一点:

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

对于想要 RFC 4122 版本 4 符合速度考虑的解决方案的人(少数电话到 Math.random()):

var rand = Math.random; 函数 UUID() { var nbr, randStr = "; do { randStr += (nbr = rand()).toString(16).substr(3, 6); } 同时(randStr.length < 30); 返回( randStr.substr(0, 8) + "-" + randStr.substr(8, 4) + "-4" + randStr.substr(12, 3) + "-" + ((nbr*4♰0) +8).toString(16) + // [89ab] randStr.substr(15, 3) + "-" + rand

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

[编辑 2021-10-16 以反映 RFC4122 符合 UUID 的最新最佳做法]

大多数读者在这里会想使用 uuid 模块,它已被测试和支持。

如果其中没有一个为您工作,则有这个方法(基于这个问题的原始答案):函数 uuidv4() {返回([1e7]+-1e3+-4e3+-8e3+-1e11)。代替(/[018]/g,c =>(c ^ crypto.getRandomValues(新Uint8Array(1))[0] & 15 >> c / 4).toString(16) ; } console.log(uuidv4());

注意:依靠 Math.random() 的任何 UUID 发电机的使用是由于这里最好的解释而受到强烈的拒绝(包括此答案的以前版本中显示的剪辑) TL;DR:基于 Math.random() 的解决方案不提供良好的独特性保证。

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

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

我以为值得指出的是,没有GUID发电机可以保证独特的钥匙(查看维基百科文章)。总是有冲突的可能性。