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

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


当前回答

ES6 样品

const guid=()=> {
  const s4=()=> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);     
  return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4() + s4() + s4()}`;
}

其他回答

这里有很多正确的答案,但不幸的是,包含的代码样本是相当密码和难以理解的。

请注意,随后的代码使用二进制字母以提高可读性,因此需要ECMAScript 6。

Node.js 版本

function uuid4() {
  let array = new Uint8Array(16)
  crypto.randomFillSync(array)

  // Manipulate the 9th byte
  array[8] &= 0b00111111 // Clear the first two bits
  array[8] |= 0b10000000 // Set the first two bits to 10

  // Manipulate the 7th byte
  array[6] &= 0b00001111 // Clear the first four bits
  array[6] |= 0b01000000 // Set the first four bits to 0100

  const pattern = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  let idx = 0

  return pattern.replace(
    /XX/g,
    () => array[idx++].toString(16).padStart(2, "0"), // padStart ensures a leading zero, if needed
  )
}

浏览器版本

只有第二条线是不同的。

function uuid4() {
  let array = new Uint8Array(16)
  crypto.getRandomValues(array)

  // Manipulate the 9th byte
  array[8] &= 0b00111111 // Clear the first two bits
  array[8] |= 0b10000000 // Set the first two bits to 10

  // Manipulate the 7th byte
  array[6] &= 0b00001111 // Clear the first four bits
  array[6] |= 0b01000000 // Set the first four bits to 0100

  const pattern = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  let idx = 0

  return pattern.replace(
    /XX/g,
    () => array[idx++].toString(16).padStart(2, "0"), // padStart ensures a leading zero, if needed
  )
}

测试

最后,相应的测试(Jasmine)。

describe(".uuid4()", function() {
  it("returns a UUIDv4 string", function() {
    const uuidPattern = "XXXXXXXX-XXXX-4XXX-YXXX-XXXXXXXXXXXX"
    const uuidPatternRx = new RegExp(uuidPattern.
      replaceAll("X", "[0-9a-f]").
      replaceAll("Y", "[89ab]"))

    for (let attempt = 0; attempt < 1000; attempt++) {
      let retval = uuid4()
      expect(retval.length).toEqual(36)
      expect(retval).toMatch(uuidPatternRx)
    }
  })
})

UUID v4 解释

非常好的解释 UUID 版本 4 在这里: 创建一个符合 RFC 4122 的 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 */
}

在这里,你可以找到一个非常小的功能,产生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 生成一個静態 UUID 如果沒有連線提供:

函数 stringToUUID(str) {如果(str === 未定义 <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk> <unk>

吉普赛

如果您只需要任何特定格式的随机 128 位序列,您可以使用:

function uuid() {
    return crypto.getRandomValues(new Uint32Array(4)).join('-');
}

这将返回像2350143528-4164020887-938913176-2513998651这样的东西。