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

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


当前回答

我找不到使用单一 16-octet TypedArray 和 DataView 的任何答案,所以我认为在 RFC 中创建版本 4 UUID 的下列解决方案将自行存在:

const uuid4 = () => {
    const ho = (n, p) => n.toString(16).padStart(p, 0); /// Return the hexadecimal text representation of number `n`, padded with zeroes to be of length `p`
    const data = crypto.getRandomValues(new Uint8Array(16)); /// Fill the buffer with random data
    data[6] = (data[6] & 0xf) | 0x40; /// Patch the 6th byte to reflect a version 4 UUID
    data[8] = (data[8] & 0x3f) | 0x80; /// Patch the 8th byte to reflect a variant 1 UUID (version 4 UUIDs are)
    const view = new DataView(data.buffer); /// Create a view backed by a 16-byte buffer
    return `${ho(view.getUint32(0), 8)}-${ho(view.getUint16(4), 4)}-${ho(view.getUint16(6), 4)}-${ho(view.getUint16(8), 4)}-${ho(view.getUint32(10), 8)}${ho(view.getUint16(14), 4)}`; /// Compile the canonical textual form from the array data
};

我更喜欢,因为:

它只依赖于标准 ECMAScript 平台的功能,在可能的情况下 - 这只是一个程序它只使用一个单一的泡沫,尽量减少数据的复制,这在理论上应该带来性能优势。

在写这篇文章时, getRandomValues 不是在 Node.js 中的加密对象中实施的东西,但是它具有相同的随机Bytes 功能,可以用来代替它。

其他回答

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

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

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

一个简单的解决方案来创建一个独特的识别是使用一个时间标记,并添加一个随机号码。

下面的功能将产生类型的随机序列: uuid-14d93eb1b9b4533e6. 不需要产生32个字符的随机序列. 在这种情况下,16个字符的随机序列不足以提供JavaScript中的独特 UUID。

var createUUID = function() {
  return "uuid-" + ((new Date).getTime().toString(16) + Math.floor(1E7*Math.random()).toString(16));
}
  // RFC 4122
  //
  // A UUID is 128 bits long
  //
  // String representation is five fields of 4, 2, 2, 2, and 6 bytes.
  // Fields represented as lowercase, zero-filled, hexadecimal strings, and
  // are separated by dash characters
  //
  // A version 4 UUID is generated by setting all but six bits to randomly
  // chosen values
  var uuid = [
    Math.random().toString(16).slice(2, 10),
    Math.random().toString(16).slice(2, 6),

    // Set the four most significant bits (bits 12 through 15) of the
    // time_hi_and_version field to the 4-bit version number from Section
    // 4.1.3
    (Math.random() * .0625 /* 0x.1 */ + .25 /* 0x.4 */).toString(16).slice(2, 6),

    // Set the two most significant bits (bits 6 and 7) of the
    // clock_seq_hi_and_reserved to zero and one, respectively
    (Math.random() * .25 /* 0x.4 */ + .5 /* 0x.8 */).toString(16).slice(2, 6),

    Math.random().toString(16).slice(2, 14)].join('-');

只有在任何人落下谷歌正在寻找一个小用途图书馆的情况下,ShortId满足了这个问题的所有要求,它允许指定允许的字符和长度,并保证不序列,不重复的线条。

为了使这一点更为真实的答案,该图书馆的核心使用下列逻辑来制作其简短的ID:

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

它只是扩展 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
    }
}