如何在JavaScript中创建GUID(全局唯一标识符)?GUID / UUID应至少为32个字符,并应保持在ASCII范围内,以避免在传递时出现问题。
我不确定所有浏览器都可用哪些例程,内置的随机数生成器有多“随机”和有多少种子等信息。
如何在JavaScript中创建GUID(全局唯一标识符)?GUID / UUID应至少为32个字符,并应保持在ASCII范围内,以避免在传递时出现问题。
我不确定所有浏览器都可用哪些例程,内置的随机数生成器有多“随机”和有多少种子等信息。
如果您将 let buffer = new Uint8Array(); crypto.getRandomValues
替换为 let buffer = crypto.randomBytes(16)
,这也适用于Node.js。
在性能上,它应该能够击败大多数正则表达式的解决方案。
const hex = '0123456789ABCDEF'
let generateToken = function() {
let buffer = new Uint8Array(16)
crypto.getRandomValues(buffer)
buffer[6] = 0x40 | (buffer[6] & 0xF)
buffer[8] = 0x80 | (buffer[8] & 0xF)
let segments = []
for (let i = 0; i < 16; ++i) {
segments.push(hex[(buffer[i] >> 4 & 0xF)])
segments.push(hex[(buffer[i] >> 0 & 0xF)])
if (i == 3 || i == 5 || i == 7 || i == 9) {
segments.push('-')
}
}
return segments.join('')
}
for (let i = 0; i < 100; ++i) {
console.log(generateToken())
}
性能图表(大家都喜欢它们):jsbench
这是什么样子
let uuid = function(){
return Array
.from(Array(16))
.map(e => Math.floor(Math.random() * 255)
.toString(16)
.padStart(2,"0"))
.join('')
.match(/.{1,4}/g)
.join('-')
}
console.log(uuid())
console.log(uuid())
function NewGuid()
{
var sGuid = "";
for (var i=0; i<32; i++)
{
sGuid += Math.floor(Math.random()*0xF).toString(0xF);
}
return sGuid;
}
如果有人在Google上寻找小型实用程序库,ShortId符合此问题的所有要求。它允许指定允许的字符和长度,并保证非连续、非重复字符串。
为了使答案更加实用,该库的核心使用以下逻辑生成其短标识:
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
var myGuid = GUID();
Math.random
(https://github.com/dustinpoissant/GUIDJS/blob/62c1dd3af36ea7e23194ac89386ca51ac2d4b541/src/GUID.js#L5)。因此,在浏览器中,如果 Math.random
实现不好,它可能会出现问题并且容易发生冲突。建议使用 uuid,因为它在可用的情况下使用了 crypto
API。 - Mark Amery在这里,您可以找到一个生成 UUID 的非常小的函数。
其中的最终版本是:
function b(
a // Placeholder
){
var cryptoObj = window.crypto || window.msCrypto; // For Internet Explorer 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包很容易实现。 https://www.npmjs.com/package/uuid
const { v4: uuidv4 } = require('uuid');
uuidv4(); // ⇨ '1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed'
function stringToUUID (str)
{
if (str === undefined || !str.length)
str = "" + Math.random() * new Date().getTime() + Math.random();
let c = 0,
r = "";
for (let i = 0; i < str.length; i++)
c = (c + (str.charCodeAt(i) * (i + 1) - 1)) & 0xfffffffffffff;
str = str.substr(str.length / 2) + c.toString(16) + str.substr(0, str.length / 2);
for(let i = 0, p = c + str.length; i < 32; i++)
{
if (i == 8 || i == 12 || i == 16 || i == 20)
r += "-";
c = p = (str[(i ** i + p + 1) % str.length]).charCodeAt(0) + p + i;
if (i == 12)
c = (c % 5) + 1; //1-5
else if (i == 16)
c = (c % 4) + 8; //8-B
else
c %= 16; //0-F
r += c.toString(16);
}
return r;
}
console.log("Random :", stringToUUID());
console.log("Static [1234]:", stringToUUID("1234")); //29c2c73b-52de-4344-9cf6-e6da61cb8656
console.log("Static [test]:", stringToUUID("test")); //e39092c6-1dbb-3ce0-ad3a-2a41db98778c
基于@broofa的最高评价答案,这是一个最简单的JavaScript实现guid
的方法,只需要3行代码。
var guid = () => {
var w = () => { return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); }
return `${w()}${w()}-${w()}-${w()}-${w()}-${w()}${w()}${w()}`;
}
当在控制台中执行时,会产生以下输出。
{{link1:}}
function random() {
const
fourBytesOn = 0xffffffff, // 4 bytes, all 32 bits on: 4294967295
c = typeof crypto === "object"
? crypto // Node.js or most browsers
: typeof msCrypto === "object" // Stinky non-standard Internet Explorer
? msCrypto // eslint-disable-line no-undef
: null; // What old or bad environment are we running in?
return c
? c.randomBytes
? parseInt(c.randomBytes(4).toString("hex"), 16) / (fourBytesOn + 1) - Number.EPSILON // Node.js
: c.getRandomValues(new Uint32Array(1))[0] / (fourBytesOn + 1) - Number.EPSILON // Browsers
: Math.random();
}
function uuidV4() { // eslint-disable-line complexity
// If possible, generate a single random value, 128 bits (16 bytes)
// in length. In an environment where that is not possible, generate
// and make use of four 32-bit (4-byte) random values.
// Use crypto-grade randomness when available, else Math.random()
const
c = typeof crypto === "object"
? crypto // Node.js or most browsers
: typeof msCrypto === "object" // Stinky non-standard Internet Explorer
? msCrypto // eslint-disable-line no-undef
: null; // What old or bad environment are we running in?
let
byteArray = c
? c.randomBytes
? c.randomBytes(16) // Node.js
: c.getRandomValues(new Uint8Array(16)) // Browsers
: null,
uuid = [ ];
/* eslint-disable no-bitwise */
if ( ! byteArray) { // No support for generating 16 random bytes
// in one shot -- this will be slower
const
int = [
random() * 0xffffffff | 0,
random() * 0xffffffff | 0,
random() * 0xffffffff | 0,
random() * 0xffffffff | 0
];
byteArray = [ ];
for (let i = 0; i < 256; i++) {
byteArray[i] = int[i < 4 ? 0 : i < 8 ? 1 : i < 12 ? 2 : 3] >> i % 4 * 8 & 0xff;
}
}
byteArray[6] = byteArray[6] & 0x0f | 0x40; // Always 4, per RFC, indicating the version
byteArray[8] = byteArray[8] & 0x3f | 0x80; // Constrained to [89ab], per RFC for version 4
for (let i = 0; i < 16; ++i) {
uuid[i] = (byteArray[i] < 16 ? "0" : "") + byteArray[i].toString(16);
}
uuid =
uuid[ 0] + uuid[ 1] + uuid[ 2] + uuid[ 3] + "-" +
uuid[ 4] + uuid[ 5] + "-" +
uuid[ 6] + uuid[ 7] + "-" +
uuid[ 8] + uuid[ 9] + "-" +
uuid[10] + uuid[11] + uuid[12] + uuid[13] + uuid[14] + uuid[15];
return uuid;
/* eslint-enable no-bitwise */
}
BigInt
和ES6类以及其他技术,可以实现每秒500,000个uuid的速率。参见参考链接 - smallscriptURL.createObjectURL(new Blob()).substr(-36)
即可。该方法得到了很好的浏览器支持。为避免内存泄漏,需要调用URL.revokeObjectURL(url)
。 - rinogo