如何创建GUID / UUID?

5319

如何在JavaScript中创建GUID(全局唯一标识符)?GUID / UUID应至少为32个字符,并应保持在ASCII范围内,以避免在传递时出现问题。

我不确定所有浏览器都可用哪些例程,内置的随机数生成器有多“随机”和有多少种子等信息。


38
GUIDs表示为字符串时,长度至少为36个字符,最多不超过38个字符,并匹配模式^{?[a-zA-Z0-9]{36}?}$,因此始终为ASCII码。 - AnthonyWJones
5
David Bau在http://davidbau.com/archives/2010/01/30/random_seeds_coded_hints_and_quintillions.html提供了一个更好的、可初始化的随机数生成器。我在http://blogs.cozi.com/tech/2010/04/generating-uuids-in-javascript.html中记录了一种略微不同的生成UUID的方法。 - George V. Reilly
1
很奇怪还没有人提到这一点,但为了完整起见,在npm上有大量的guid生成器。我敢打赌它们中的大多数也可以在浏览器中使用。 - George Mauer
2
12年后,使用BigInt和ES6类以及其他技术,可以实现每秒500,000个uuid的速率。参见参考链接 - smallscript
5
如其他人所提到的,如果您只在浏览器中生成少量uuid,则只需使用URL.createObjectURL(new Blob()).substr(-36)即可。该方法得到了很好的浏览器支持。为避免内存泄漏,需要调用 URL.revokeObjectURL(url) - rinogo
显示剩余2条评论
73个回答

12

如果您的环境是 SharePoint,那么有一个名为 SP.Guid.newGuid 的实用函数 (MSDN 链接) 可以创建一个新的 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;
};

重定向的 URL 显示:“适用于:SharePoint Foundation 2010”。 - Peter Mortensen

12

这个基于日期,加了随机后缀以“确保”唯一性。

它对于CSS标识符很有效,总是返回类似uid-139410573297741的东西,并且易于被黑客攻击:

uid-139410573297741

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

11

受到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());

这是使用 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());


10

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

yarn add uuid

然后:

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

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

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

了解更多信息,请访问这里的npm页面。


7
最简单的实现方式如下:
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();  
}

7

基于crypto API的 TypeScript 版本,参考自 broofa在2017-06-28更新的版本

function genUUID() {
    // Reference: https://dev59.com/7HVD5IYBdhLWcg3wDXF3#2117523
    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)
    })
}

原因:

  • number[]number 之间使用 + 是无效的。
  • string 转换为 number 必须是显式的。

这仍然会出现错误:“意外的 '&' 和 '>>' 混合。使用括号来澄清操作的预期顺序。因此,也许更好的写法是:return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> c / 4)).toString(16); - Willster

7

使用经过多人维护的、经过充分测试的代码非常重要,而不是为此编写自己的代码。

这可能是你更喜欢最稳定的代码而不是最短的 clever 版本的地方,尽管它可以在 X 浏览器中工作,但它并没有考虑到 Y 的特殊情况,这经常会导致只针对某些用户随机出现的非常难以调查的错误。个人建议使用位于 https://github.com/aurigadl/uuid-js 的 uuid-js,该库支持 Bower,因此可以轻松更新。


6
你可以使用npm包guid,一个GUID生成器和验证器。
例如:
Guid.raw();
// -> '6fdf6ffc-ed77-94fa-407e-a7b86ed9e59d'

注意:此软件包已被弃用。请使用uuid代替。

示例:

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

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

浏览器版本

只有第二行不同。

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

测试

最后,对应的测试(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)
    }
  })
})

UUID v4解释

关于UUID版本4的很好的解释在这里:生成符合RFC 4122标准的UUID

最后的说明

此外,有很多第三方包。但是,只要您只有基本需求,我不建议使用它们。真的没有多少可赢的,却有很多可失去的。作者可能追求最微小的性能提升,"修复"本来不应该修复的问题,涉及到安全时,这是一个有风险的想法。同样,他们可能会引入其他错误或不兼容性。谨慎地更新需要时间。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接