开发者问题收集

如何创建 GUID/UUID?

2008-09-19
3115418

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

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

3个回答

[于 2023-03-05 编辑,以反映生成符合 RFC4122 的 UUID 的最新最佳实践]

crypto.randomUUID() 现已成为所有现代浏览器和 JS 运行时的标准。但是,由于 新的浏览器 API 仅限于安全上下文 ,因此此方法仅适用于本地( localhost127.0.0.1 )或通过 HTTPS 提供的页面。

对于对其他 UUID 版本感兴趣、在旧平台或非安全上下文中生成 UUID 的读者,可以使用 uuid 模块 。它经过了充分的测试和支持。

function uuidv4() {
  return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
    (+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
  );
}

console.log(uuidv4());

注意: 强烈不建议使用任何依赖于 Math.random() 的 UUID 生成器 (包括此答案先前版本中的代码片段),原因 此处有最好的解释 TL;DR: 基于 Math.random() 的解决方案不能提供良好的唯一性保证。

2010-01-22

根据 RFC 4122 ,UUID(通用唯一标识符)也称为 GUID(全局唯一标识符),是旨在提供某些唯一性保证的标识符。

虽然可以用几行 JavaScript 代码实现符合 RFC 标准的 UUID(例如,参见下面的 @broofa 的回答 ),但仍存在几个常见的陷阱:

  • 无效的 ID 格式(UUID 必须采用“ xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx ”格式,其中 x 是 [0-9, a-f] 之一 M 是 [1-5] 之一, N 是 [8、9、a 或 b]
  • 使用低质量的随机源(例如 Math.random

因此,鼓励为生产环境编写代码的开发人员使用严格、维护良好的实现,例如 uuid 模块。

2008-09-19

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

这是一个类似的 RFC4122 版本 4 兼容解决方案,它通过将前 13 个十六进制数偏移时间戳的十六进制部分来解决该问题,并且一旦用尽偏移量,则偏移量为自页面加载以来的微秒数的十六进制部分。这样,即使 Math.random 位于相同的种子上,两个客户端也必须在页面加载后生成完全相同微秒数的 UUID(如果支持高性能时间)并且在完全相同的毫秒内(或 10,000 多年后)获得相同的 UUID:

function generateUUID() { // Public Domain/MIT
    var d = new Date().getTime();//Timestamp
    var d2 = ((typeof performance !== 'undefined') && 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);
    });
}

var onClick = function(){
    document.getElementById('uuid').textContent = generateUUID();
}
onClick();
#uuid { font-family: monospace; font-size: 1.5em; }
<p id="uuid"></p>
<button id="generateUUID" onclick="onClick();">Generate UUID</button>

这里有一个小提琴要测试。


ES6 的现代化代码片段

const generateUUID = () => {
  let
    d = new Date().getTime(),
    d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0;
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    let r = Math.random() * 16;
    if (d > 0) {
      r = (d + r) % 16 | 0;
      d = Math.floor(d / 16);
    } else {
      r = (d2 + r) % 16 | 0;
      d2 = Math.floor(d2 / 16);
    }
    return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
  });
};

const onClick = (e) => document.getElementById('uuid').textContent = generateUUID();

document.getElementById('generateUUID').addEventListener('click', onClick);

onClick();
#uuid { font-family: monospace; font-size: 1.5em; }
<p id="uuid"></p>
<button id="generateUUID">Generate UUID</button>
2012-01-10