在javascript中创建guid/uuid?

Create GUID / UUID in JavaScript?

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

guid/uuid至少应为32个字符,并应保持在ascii范围内,以避免在传递时出现问题。


对于一个RFC4122版本的4顺应性溶液,这个单线(ISH)溶液是我最紧凑的溶液。

1
2
3
4
5
6
7
8
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())

Update,2015-06-02:Be aware that UUUID uniqueness relies heavily on the underlying random number generator(RNG).专利解决方案,但不能保证高质量的RNG。See Adam Hyland's excellent writeup on math.random()for details.对于一种更强有力的解决办法,考虑象UUUID模块[Disclaimer:I'm the author],它使用的是高质量的RNG Apis where available.

最新资料,2015-08-26:作为一个侧注,本说明说明说明如何确定在达到一定的碰撞概率之前,如何产生许多IDS。以3.26x1015版本4 RFC4122 UUUIDS为例,你有1-in-a-million chance of collision.

最新版本,2017-06-28:一篇好文章,来自铬开发公司,讨论铬、firefox和safari的数学状态。TL;DR-as of late-2015 is"pretty good",但不是加密质量。To address that issue,here's an updated version of the above solution that uses ES6,the cryptoapi,and a bit of JS wizardy I can't take credit for:

ZZU1


(universally独特的标识符(UUID),也被称为GUID(全局唯一标识符),根据RFC 4122唯一性标识符,是与一定的保证。

最好的方式来跟踪他们的生成,是执行的指令使用一个RFC中说,在许多社区vetted开源实现,或是有它的语言,使用内置的实现。

一些开源工具与工作的例子UUID是流行的编程语言,一些上市公司在这里。

JavaScript

  • http:/ / / / kelektiv github.com节点。

PHP的

  • https:////github.com拉姆齐。

GO

  • github.com https:////go.uuid顿悟

红宝石

  • 的标准库的一部分

Python

  • 在该模块。

请注意,只有通过随机生成的标识符字节的字节,字符或字符),将不会给你相同的协调通信的实现。另外,非常重要的工作与系统兼容,可以选择不接受的UUID随机生成酮,和许多开源validators将实际检查是有效的结构。

这一必备的UUID格式:

1
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

在M和N的位置可能有一定的价值。在这个时间,是唯一有效的值,m是1,2,3,4和5的操作系统,这将使大部分的位置随机产生不可接受的结果。


我真的喜欢布鲁法索的答案是什么,但这是不幸的,因为这是一个穷人实现Math.random的机会。

这是一个类似的RFC4122版本,第4版,遵循的解决办法是,将第一个13 Hex numbers by a hex partion of the timestamp搁置一边。这样,即使是Math.random的种子上,客户也必须在同一毫秒(或1万年后)生成UUUID,以便获得相同的UUUID:

1
2
3
4
5
6
7
8
9
10
11
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);
    });
}

这是一个忠实的测试。


别斯法的回答相当圆滑,确实-非常聪明,真的…符合RFC4122,可读性好,紧凑。令人惊叹的!好的。

但是,如果你在看正则表达式,那么许多replace()回调、toString()Math.random()函数调用(其中他只使用了4位结果并浪费了其余的部分),你可能会开始怀疑性能。实际上,Joelpt甚至决定放弃使用generateQuickGUID来实现通用的guid速度。好的。

但是,我们能得到速度和RFC遵从性吗?我说,是的!我们能保持可读性吗?好。。。不完全是,但如果你跟着走很容易。好的。

但首先,我的研究结果与思伯法、guid和不符合RFC的generateQuickGUID相比:好的。

1
2
3
4
5
6
7
8
9
10
11
12
                  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://jspef.com/uuid-generator-opt/4上提供了完整的源代码。好的。

为了得到解释,我们先从别斯法的代码开始:好的。

1
2
3
4
'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(按照RFC规范强制最前面的2位到10),并且regex不匹配-4字符,因此他不必处理它们。非常,非常圆滑。好的。

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

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

1
2
3
4
5
6
7
8
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%丢弃在一个随机缓冲区中,这个缓冲区在每次迭代中都会被移出。我们还将该模板定义移出循环,以防它有助于:好的。

1
2
3
4
5
6
7
8
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)的工作:好的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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()函数之外只构建一次。好的。

1
2
3
4
5
6
7
8
9
10
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
}

我尝试了一个E6(),它一次处理16位,仍然使用256元素LUT,它显示了优化的收益递减。虽然它的迭代次数较少,但内部逻辑却因处理量的增加而变得复杂,而且在桌面上执行相同的操作,而在移动设备上只快了约10%。好的。

应用的最终优化技术-展开循环。既然我们循环了固定的次数,我们就可以用手把这些都写出来。我曾经用一个随机变量r尝试过这个方法,我一直在重新分配它,结果性能下降了。但是,当四个变量预先分配随机数据,然后使用查找表,并应用适当的RFC位时,这个版本会将它们全部清除:好的。

1
2
3
4
5
6
7
8
9
10
11
12
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];
}

修改:http://jcward.com/uuid.js-UUID.generate()。好的。

有趣的是,生成16字节的随机数据很容易。整个技巧是用符合RFC的字符串格式表示它,并且它最紧密地完成了16字节的随机数据、展开的循环和查找表。好的。

我希望我的逻辑是正确的——在这种单调乏味的工作中很容易出错。但我觉得产出不错。我希望您喜欢这个疯狂的代码优化过程!好的。

建议:我的主要目标是展示和教授潜在的优化策略。其他的答案包括一些重要的主题,比如碰撞和真正的随机数,这些对于生成良好的UUID很重要。好的。好啊。


这里的一些代码,基于RFC 4122第4.4(UUID算法创建一个从真正的随机或伪随机数)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}


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

1
2
document.getElementById("unique").innerHTML =
  Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36);
1
 

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

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

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

如果确实需要符合RFC,则此格式将作为有效的版本4 GUID传递:

1
2
3
4
var u = (new Date()).getTime().toString(16) +
    Math.random().toString(16).substring(2) +"0".repeat(16);
var guid = u.substr(0,8) + '-' + u.substr(8,4) + '-4000-8' +
    u.substr(12,3) + '-' + u.substr(15,12);

1
2
3
4
5
var u = (new Date()).getTime().toString(16) +
    Math.random().toString(16).substring(2) +"0".repeat(16);
var guid = u.substr(0,8) + '-' + u.substr(8,4) + '-4000-8' +
    u.substr(12,3) + '-' + u.substr(15,12);
document.getElementById("unique").innerHTML = guid;
1
 

编辑:上面的代码遵循的是强度,而不是RFC的字母。除其他差异外,它是一些随机数字的短。(如果需要,可以添加更多的随机数字)好处是,与100%兼容的代码相比,这真的很快。你可以在这里测试你的guid


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

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

功能简单如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * Generates a GUID string.
 * @returns {String} The generated GUID.
 * @example af8a8416-6e18-a307-bd9c-f2c947bbb3aa
 * @author Slavik Meltser ([email protected]).
 * @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();
}

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

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

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

算法:

  • Math.random()函数返回一个介于0和1之间的十进制数,小数点后有16位数字(用于示例0.4363923368509859
  • 然后我们把这个号码转换成它是以16为基数的字符串(从上面的示例中,我们将得到0.6fb7687fMath.random().toString(16)
  • 然后切断0.前缀(0.6fb7687f=>6fb7687f,得到一个十六进制的字符串字符长。(Math.random().toString(16).substr(2,8)
  • 有时,Math.random()函数将返回较短的数字(例如0.4363),因为结尾处有零(从上面的例子来看,实际上数字是0.4363000000000000)。这就是为什么我要附加到这个字符串"000000000"(一个有9个零的字符串),然后用substr()函数将它切断,使它精确到9个字符(在右边填充0)。
  • 精确加9个零的原因是因为更糟的情况,即当Math.random()函数将返回0或1(每一个0或1/10^16的概率)。这就是为什么我们需要给它加9个零("0"+"000000000""1"+"000000000"),然后将它从第二个索引(第三个字符)中去掉,长度为8个字符。对于其余的情况,加零不会损害结果,因为它无论如何都会切断结果。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-XXXXXXXXXXXX
  • 为了区分这两种类型,我在pair creator函数_p8(s)中添加了一个标志参数,s参数告诉函数是否添加破折号。
  • 最后,我们使用以下链接构建guid:_p8() + _p8(true) + _p8(true) + _p8(),并返回它。

链接到我的日志

享受!-)


这是一个顶级选票的组合,与铬碰撞的工厂:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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);
        });
    };

如果你想测试的话


这是从用户Jed在https://gist.github.com/982883中的一个解决办法,日期为2011年10月9日:

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

这实现了相同的目标,即当前的高回复率,但在50+2+个字节中,通过利用强化、回归和指数记分。For those curious how it works,here's the annotated form of an older version of the function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
      )
}


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

1
2
3
4
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下进行的,每次迭代1000万次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
>>> 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

这是时间码。

1
2
3
4
5
6
var r;
console.time('t');
for (var i = 0; i < 10000000; i++) {
    r = FuncToTest();
};
console.timeEnd('t');

从shkedy’s技术博客:史记

1
2
3
4
5
6
7
8
9
10
11
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生成器可以保证在出独特的键(检查维基百科的文章)。总是有一个碰撞的机会。提供了指导设计的大宇宙(键)减少到几乎无变化。


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

简单,快速生成rfc4122 uuid。

特征:

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

使用NPM安装:

1
npm install uuid

或者通过浏览器使用UUID:

下载原始文件(uuid v1):https://raw.githubusercontent.com/kelektv/node-uuid/master/v1.js下载原始文件(uuid v4):https://raw.githubusercontent.com/kelektv/node-uuid/master/v4.js

想要更小的吗?请访问:https://gist.github.com/jed/982883

用途:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 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:

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


Web服务将是有益的。

google发现:http:////guidgenerator www.hoskinson.net

不能认为这是必须的,但有人发布实施,在真正的GUID生成器。

这样可以使你的Web服务的发展,Web接口的GUID是REST Web服务的异种类型,它是通过JavaScript和AJAX在浏览器中。


1
2
3
4
5
6
7
8
9
10
11
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的解答和一些位操作员的版本,从缓冲器中提取大小的窗口。

应该坚持RFC类型4(随机)Schema,自从我上一次遇到问题后,不遵守UUUIDS与Java's UUUUID。


简单的javascript模块作为这个线程中最佳答案的组合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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"

< /块引用>


从良好的OL的维基百科的链接有一个JavaScript错误的实现。

fairly看来也许是优雅的,可以通过采用改进的哈希salting的客户端的IP地址。这可能是哈希可以插入的HTML文件,服务器端使用JavaScript的客户端。

更新:原来的网站已经有最新的版本是洗牌,在这里


好吧,这已经有很多答案了,但不幸的是,在这一组中没有一个"真实"的随机答案。下面的版本是对别斯法答案的改编,但更新后包含了一个"真"随机函数,在可用的情况下使用加密库,以及alea()函数作为回退。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
  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 http://baagoe.com/en/RandomMusings/javascript/
      // Johannes Baag??e <[email protected]>, 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 <[email protected]>, 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);
  });
};


GitHub上的javascript项目-https://github.com/liosk/uuid.js

UUID.js The RFC-compliant UUID generator for JavaScript.

See RFC 4122 http://www.ietf.org/rfc/rfc4122.txt.

Features Generates RFC 4122 compliant UUIDs.

Version 4 UUIDs (UUIDs from random numbers) and version 1 UUIDs
(time-based UUIDs) are available.

UUID object allows a variety of access to the UUID including access to
the UUID fields.

Low timestamp resolution of JavaScript is compensated by random
numbers.


这第4版(创建的UUID创建从伪随机数):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  // 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('-');


用一些外在的东西来调整我自己的发电机。

我用Kybos随机数发生器做一个比特加密声音。

下面是我的剧本,用的是面部和Kybos方法,从Baagoe.com除外。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//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 <[email protected]>, 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

]+|[\{\}]|[\s

]+$/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));

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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);
        }
    );
};

更好的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
 }

最小化:

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

ES6样品

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


这一个基于日期,并添加一个随机后缀以"确保"唯一性。对于CSS标识符很有效。它总是返回类似的内容,并且很容易被黑客攻击:

UID-139410573297741

1
2
3
4
5
6
7
8
9
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;
        };

对于那些想要一个符合RFC4122版本4的解决方案,考虑到速度(很少调用math.random()):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function UUID() {
    var nbr, randStr ="";
    do {
        randStr += (nbr = Math.random()).toString(16).substr(2);
    } 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)
        ].join("");
}

上面的函数应该在速度和随机性之间有一个适当的平衡。


这只是一个简单的Ajax呼叫…

如果任何人仍然感兴趣,这就是我的解决办法。

On the server side:

1
2
3
4
5
[WebMethod()]
public static string GenerateGuid()
{
    return Guid.NewGuid().ToString();
}

On the client side:

1
2
3
4
5
6
7
8
9
10
11
var myNewGuid = null;
PageMethods.GenerateGuid(
    function(result, userContext, methodName)
    {
        myNewGuid = result;
    },
    function()
    {
        alert("WebService call failed.");
    }
);


有一个JQuery plugin that handles guid's nicely@http://plugin s.jquery.com/project/guid&uhelper

1
jQuery.Guid.Value()

Returns value of internal guid.如果没有具体说明,则返回一个新的单元(价值在保存内部)。

1
jQuery.Guid.New()

让我们回到一个新的地方,把它当作内部价值。

1
jQuery.Guid.Empty()

Returns an empty guid 000000-0000-0000-0000-0000-00000000000.

1
jQuery.Guid.IsEmpty()

回到布林真实的假如空虚的话

1
jQuery.Guid.IsValid()

回到布林真实有效的指引,假如不。

1
jQuery.Guid.Set()

我们回去吧设置特殊的用户名,如果无效,退回一个空白的用户名。


我知道,这是个老问题。为了完整起见,如果您的环境是SharePoint,那么有一个名为SP.Guid.newGuid的实用程序函数(msdn link),它创建了一个新的guid。此函数在sp.init.js文件中。如果重写此函数(从其他私有函数中删除一些其他依赖项),则如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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;
};

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

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

它将返回类似于2350143528-4164020887-938913176-2513998651的内容。


只是另一个更易读的变体,只有两个突变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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, '-');
}


在支持的浏览器(ie11+、ios7+、ff21+、chrome、android chrome)上使用crypto.getRandomValues(a)的简单代码。避免使用Math.random(),因为这会导致冲突(例如,在muxa的实际情况下,4000个生成的uuid发生20个冲突)。

1
2
3
4
5
6
7
8
9
10
11
12
13
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在我的笔记本电脑上每秒生成大约10000个uuid()的chromium来测量性能。
  • 只对"y"使用8,因为这简化了代码的可读性(y可以是8、9、a或b)。


重要的是要使用由1个以上的贡献者维护的经过良好测试的代码,而不是为此而牺牲自己的东西。这是一个地方,你可能希望最稳定的代码比最短的可能聪明的版本,在X浏览器工作,但不考虑到Y的特性,这往往会导致非常难以调查的错误,而不是清单只是随机为一些用户。我个人在https://github.com/aurigadl/uuid-js上使用uuid-js,这是Bower启用的,所以我可以很容易地获取更新。


您可以使用NPM包guid、guid生成器和验证器。

网址:https://www.npmjs.com/package/guid

例子:

1
2
Guid.raw();
// -> '6fdf6ffc-ed77-94fa-407e-a7b86ed9e59d'

更新:此包已被弃用。改为使用UUID。

网址:https://www.npmjs.com/package/uuid

例子:

1
2
const uuidv4 = require('uuid/v4');
uuidv4(); // ? '10ba038e-48da-487b-96e8-8d3b99b6d18a'


为了防止任何一个从谷歌上掉下来的人正在寻找一个小型的实用程序库,shortid(https://www.npmjs.com/package/shortid)满足了这个问题的所有要求。它允许指定允许的字符和长度,并保证非连续、非重复的字符串。

为了使这更真实,该库的核心使用以下逻辑生成其简短的ID:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function encode(lookup, number) {
    var loopCounter = 0;
    var done;

    var str = '';

    while (!done) {
        str = str + lookup( ( (number >> (4 * loopCounter)) & 0x0f ) | randomByte() );
        done = number < (Math.pow(16, loopCounter + 1 ) );
        loopCounter++;
    }
    return str;
}

/** Generates the short id */
function generate() {

    var str = '';

    var seconds = Math.floor((Date.now() - REDUCE_TIME) * 0.001);

    if (seconds === previousSeconds) {
        counter++;
    } else {
        counter = 0;
        previousSeconds = seconds;
    }

    str = str + encode(alphabet.lookup, version);
    str = str + encode(alphabet.lookup, clusterWorkerId);
    if (counter > 0) {
        str = str + encode(alphabet.lookup, counter);
    }
    str = str + encode(alphabet.lookup, seconds);

    return str;
}

我并没有编辑它来只反映这种方法最基本的部分,所以上面的代码包含了库中的一些附加逻辑。如果你对它正在做的每件事都很好奇,可以看看它的来源:https://github.com/dylang/shortid/tree/master/lib


这里是一个工作示例,它生成32位唯一UUID。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function generateUUID() {
      var d = new Date();
      var k = d.getTime();
     var str = k.toString(16).slice(1)
    var UUID= 'xxxx-xxxx-4xxx-yxxx-xzx'.replace(/[xy]/g, function (c)
      {
        var r = Math.random() * 16 | 0;
        v = c == 'x' ? r : (r & 3 | 8);
        return v.toString(16);
      });
      var newString = UUID.replace(/[z]/, str)
      return newString;
    }
    var x = generateUUID()
    console.log(x,x.length)

我发现这个脚本对于在javascript中创建guid很有用

https://github.com/addui/guidjs

1
var myGuid = GUID();

我正在使用下面的函数,希望它可能有用。

1
2
3
4
5
6
7
8
9
    function NewGuid()
         {
           var sGuid="";
           for (var i=0; i<32; i++)
            {
              sGuid+=Math.floor(Math.random()*0xF).toString(0xF);
            }
           return sGuid;
         }


基于blambefa的工作,我通过在math.random()中添加时间戳来增加更多的随机性。

希望能有所帮助

1
2
3
4
5
6
7
function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = parseFloat('0.' + Math.random().toString().replace('0.', '') + new Date().getTime()) * 16 | 0,
            v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

对于在Windows上使用javascript的用户(例如wscript/cscript/mshta)。可以使用ActiveX。具体来说,Scriptlet.Typelib对象:

1
WScript.Echo((new ActiveXObject("Scriptlet.TypeLib")).Guid)

请注意,此答案仅适用于我列出的技术,它不适用于任何浏览器,甚至不适用于Microsoft Edge!所以,你的里程数会随着这个答案而变化。


对于我的用例,我需要确保在全球范围内唯一的ID生成;没有例外。我在这个问题上挣扎了一段时间,然后想出了一个名为tuid(真正唯一的id)的解决方案。它生成一个ID,前32个字符由系统生成,其余数字表示自epoch以来的毫秒数。在需要在客户端JavaScript上生成ID的情况下,它工作得很好。看一看:

https://github.com/mongoh/tuid网站


在这里,您可以找到一个生成uuids的非常小的函数https://gist.github.com/jed/982883

最终版本之一是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function b(
  a                  // placeholder
){
  var cryptoObj = window.crypto || window.msCrypto; // for IE 11
  return a           // if the placeholder was passed, return
    ? (              // a random number from 0 to 15
      a ^            // unless b is 8,
      cryptoObj.getRandomValues(new Uint8Array(1))[0]  // 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
      )
}

好的,使用uuid包,它支持版本1、3、4和5的uuid做:

1
yarn add uuid

然后:

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

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

1
2
3
4
5
6
7
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页面


我找不到任何使用单个16个八位字节的TypedArrayDataView的答案,因此我认为下面针对每个RFC生成版本4 uuid的解决方案将独立于此:

1
2
3
4
5
6
7
8
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
}

我更喜欢它,因为它只依赖于标准EcmaScript平台可用的功能。

请注意,在编写本文时,getRandomValues不是为node.js中的crypto对象实现的。但是,它具有randomBytes功能。


为了科学。我还没见过有人这样做…它不兼容v4,但可以很容易地修改为。它只是扩展uint8array类型并使用crypto.getRandomValues()生成uuid字节值的一个示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class uuid extends Uint8Array {
        constructor() {
            super(16)
            /* not v4, just some random bytes */
            window.crypto.getRandomValues(this)
        }
        toString() {
            let id = new String()
            for (let i = 0; i < this.length; i++) {
                /*convert uint8 to hex string */
                let hex = this[i].toString(16).toUpperCase()

                /*add zero padding*/
                while (hex.length < 2) {
                    hex = String(0).concat(hex)
                }
                id += hex

                /* add dashes */
                if (i == 4 || i == 6 || i == 8 || i == 10 || i == 16){
                    id += '-'
                }
            }
            return id
        }
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function randomHex(length) {
    var random_string = '';
    if(!length){
        length = 1;
    }
    for(var i=0; i<length; i+=1){
        random_string += Math.floor(Math.random() * 15).toString(16);
    }
    return random_string;
}

function guid() {
    return randomHex(8);
}

这可能对某人有用…

1
2
3
4
5
6
7
8
9
10
11
var d = new Date().valueOf();
var n = d.toString();
var result = '';
var length = 32;
var p = 0;
var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

for (var i = length; i > 0; --i){
    result += ((i & 1) && n.charAt(p) ? '' + n.charAt(p) + '' : chars[Math.floor(Math.random() * chars.length)]);
    if(i & 1) p++;
};

https://jsfiddle.net/j0evrdf1/1/


只是觉得我会用另一种方式来做同样的事情。

1
2
3
4
5
6
7
8
function guid() {
  var chars = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"];
  var str ="";
  for(var i=0;i<36;i++) {
    var str = str + ((i == 8 || i == 13 || i == 18 || i == 23) ?"-" : chars[Math.floor(Math.random()*chars.length)]);
  };
  return str;
}

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

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

1
2
3
var createUUID = function() {
  return"uuid-"+((new Date).getTime().toString(16)+Math.floor(1E7*Math.random()).toString(16));
}

我们可以使用replace和crypto.getRandomValues获得如下输出:

xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx

enter image description here

如果我们正在寻找一个opti解决方案,我们必须用一个数组(32)替换crypto.getRandomValues(new Uint8Array(1))[0]

1
2
3
4
5
6
const uuidv4 = () =>
  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  );

console.log(uuidv4());

要获取此代码:

1
2
3
4
5
6
7
8
9
10
11
12
function uuidv4() {
  let bytes = window.crypto.getRandomValues(new Uint8Array(32));
  const randomBytes = () => (bytes = bytes.slice(1)) && bytes[0];

  return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
      (c ^ randomBytes() & 15 >> c / 4).toString(16)
    );
}


for (var i = 0; i < 10; i++)
  console.log(uuidv4());

碰撞:

我们可以像谷歌分析一样,添加一个时间戳:uuidv4() +"." + (+new Date())


我最近用的那个:

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

我知道这是一个老问题,但几天前我学到了一些新的东西,我想这是一个"分享"它的好地方:

使用change.js,您可以得到一个唯一的带有一行代码的guid:

1
2
3
var chance = new Chance();

document.body.innerHTML = chance.guid();
1
body { font-family: Tahoma }
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  Chance.js
</head>
<body>
<script src="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js">
<link href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css" rel="stylesheet" type="text/css" />
  <script src="http://chancejs.com/chance.min.js">
</body>
</html>


我知道这是旧的局面,但如果你真的想创造一个你可以在没有直觉的Javascript的情况下完成这一点。你可以在每次负荷到期时,在服务器侧创建一个引导,然后在页面运行时,将该引导插入到一个Javascript变量。只是一个想法。