如何在JavaScript中创建GUID(全球独特识别器)?GUID/UUID应该至少有32个字符,并且应该保持在ASCII范围内,以避免在通过它们时遇到麻烦。

我不确定在所有浏览器上有哪些习惯,如何“随机”和种植内置的随机号码发电机等。


当前回答

对于想要 RFC 4122 版本 4 符合速度考虑的解决方案的人(少数电话到 Math.random()):

var rand = Math.random; 函数 UUID() { var nbr, randStr = "; do { randStr += (nbr = rand()).toString(16).substr(3, 6); } 同时(randStr.length < 30); 返回( randStr.substr(0, 8) + "-" + randStr.substr(8, 4) + "-4" + randStr.substr(12, 3) + "-" + ((nbr*4♰0) +8).toString(16) + // [89ab] randStr.substr(15, 3) + "-" + rand

上面的功能应该在速度和随机性之间保持适当的平衡。

其他回答

基于布罗法的答案,我有自己的答案:

这里是使用 crypto.getRandomValues 的加密更强的版本。

函数 uuidv4() { const a = crypto.getRandomValues(新 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 的更快版本,使用几乎相同的原则:

函数 uuidv4() { return '00-0-4-1-000'.replace(/[^-]/g, s => ((Math.random() + ~~s) * 0x10000 >> s).toString(16).padStart(4, '0') ); } console.log(uuidv4());

这里是一个方法,使用真实的随机通过 random.org 生成 RFC4122 如果错误,它会回到浏览器的内置加密图书馆,这应该几乎是相同的好。

async function UUID() {
    //get 31 random hex characters
    return (await (async () => {
        let output;
        try {
            //try from random.org
            output = (await (
                await fetch('https://www.random.org/integers/?num=31&min=0&max=15&col=31&base=16&format=plain&rnd=new')
            ).text())
                //get rid of whitespace
                .replace(/[^0-9a-fA-F]+/g, '')
            ;
            if (output.length != 31)
                throw '';
        }
        catch {
            output = '';
            try {
                //failing that, try getting 16 8-bit digits from crypto
                for (let num of crypto.getRandomValues(new Uint8Array(16)))
                    //interpret as 32 4-bit hex numbers
                    output += (num >> 4).toString(16) + (num & 15).toString(16);
                //we only want 31
                output = output.substr(1);
            }
            catch {
                //failing THAT, use Math.random
                while (output.length < 31)
                    output += (0 | Math.random() * 16).toString(16);
            }
        }
        return output;
    })())
        //split into appropriate sections, and set the 15th character to 4
        .replace(/^(.{8})(.{4})(.{3})(.{4})/, '$1-$2-4$3-$4-')
        //force character 20 to the correct range
        .replace(/(?<=-)[^89abAB](?=[^-]+-[^-]+$)/, (num) => (
            (parseInt(num, 16) % 4 + 8).toString(16)
        ))
    ;
}

此分類上一篇

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的答案和一些Bitwise运营商从泡沫中提取Nibble大小的窗户。

它应该遵守RFC类型4(随机)方案,因为我上次遇到麻烦与Java的UUID不符合的UUID。

最简单的功能来做到这一点:

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

易于使用一个简单的 uuid 包 https://www.npmjs.com/package/uuid

const { v4: uuidv4 } = require('uuid');
uuidv4(); // ⇨ '1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed'