如何创建 GUID/UUID?
如何在 JavaScript 中创建 GUID(全局唯一标识符)?GUID/UUID 应至少包含 32 个字符,并且应保持在 ASCII 范围内,以避免在传递时出现麻烦。
我不确定所有浏览器上都有哪些例程可用,内置随机数生成器的“随机性”和种子有多大,等等。
[于 2023-03-05 编辑,以反映生成符合 RFC4122 的 UUID 的最新最佳实践]
crypto.randomUUID()
现已成为所有现代浏览器和 JS 运行时的标准。但是,由于
新的浏览器 API 仅限于安全上下文
,因此此方法仅适用于本地(
localhost
或
127.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()
的解决方案不能提供良好的唯一性保证。
根据 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 模块。
我真的很喜欢
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>