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

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


当前回答

OK,使用 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 页面。

其他回答

以下是基于 RFC 4122 的某些代码,第 4.4 节(从真实随机或偏随机号创建 UUID 的算法)。

function createUUID() {
    // http://www.ietf.org/rfc/rfc4122.txt
    var s = [];
    var hexDigits = "0123456789abcdef";
    for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
    s[8] = s[13] = s[18] = s[23] = "-";

    var uuid = s.join("");
    return uuid;
}

我已经建立在这里提到的所有东西,以产生两倍的速度,可携带的所有环境,包括节点,并从Math.random()升级到加密强度的随机性。

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 */
}

对于那些在Windows上使用JavaScript的人(例如,Windows Script Host(WSH),CScript,和HTA)。一个可以使用ActiveX。

WScript.Echo((new ActiveXObject("Scriptlet.TypeLib")).Guid)

请注意,这个答案仅适用于我列出的技术,它不会在任何浏览器中工作,甚至不是Microsoft Edge! 因此,你的距离与这个答案不同。

它只是扩展 Uint8Array 类型的一个例子,并使用 crypto.getRandomValues() 来产生 UUID 比特值。

class uuid extends Uint8Array {
    constructor() {
        super(16)
        /* Not v4, just some random bytes */
        window.crypto.getRandomValues(this)
    }
    toString() {
        let id = new String()
        for (let i = 0; i < this.length; i++) {
            /* Convert uint8 to hex string */
            let hex = this[i].toString(16).toUpperCase()

            /* Add zero padding */
            while (hex.length < 2) {
                hex = String(0).concat(hex)
            }
            id += hex

            /* Add dashes */
            if (i == 4 || i == 6 || i == 8 || i == 10 || i == 16) {
                id += '-'
            }
        }
        return id
    }
}

UUID 与内置时间标签(发行器/发行器)

我在 date.now() 中的毫秒内使用时间印(在 Node.js 图书馆中,我将稍后提到,我从 process.hrtime.bigint() 中的 nanoseconds 使用时间印),然后随机添加 5 位数(10000-90000 )到时间印链的尽头。

由于我们将时间标记插入 UUID 线上,我们获得一个功能(好或坏 - 取决于任务) - 能够轻松地从 UUID 提取此时间标记。

Node.js 编辑

基准

点击此处查看JsBench