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

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


当前回答

只有在任何人落下谷歌正在寻找一个小用途图书馆的情况下,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

其他回答

我想了解布罗法的答案,所以我扩展了它并添加了评论:

var uuid = function () {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
        /[xy]/g,
        function (match) {
            /*
            * Create a random nibble. The two clever bits of this code:
            *
            * - Bitwise operations will truncate floating point numbers
            * - For a bitwise OR of any x, x | 0 = x
            *
            * So:
            *
            * Math.random * 16
            *
            * creates a random floating point number
            * between 0 (inclusive) and 16 (exclusive) and
            *
            * | 0
            *
            * truncates the floating point number into an integer.
            */
            var randomNibble = Math.random() * 16 | 0;

            /*
            * Resolves the variant field. If the variant field (delineated
            * as y in the initial string) is matched, the nibble must
            * match the mask (where x is a do-not-care bit):
            *
            * 10xx
            *
            * This is achieved by performing the following operations in
            * sequence (where x is an intermediate result):
            *
            * - x & 0x3, which is equivalent to x % 3
            * - x | 0x8, which is equivalent to x + 8
            *
            * This results in a nibble between 8 inclusive and 11 exclusive,
            * (or 1000 and 1011 in binary), all of which satisfy the variant
            * field mask above.
            */
            var nibble = (match == 'y') ?
                (randomNibble & 0x3 | 0x8) :
                randomNibble;

            /*
            * Ensure the nibble integer is encoded as base 16 (hexadecimal).
            */
            return nibble.toString(16);
        }
    );
};

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

基于布罗法的作品,我添加了一些更多的随机性,通过添加时间表到 math.random():

function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = parseFloat('0.' + Math.random().toString().replace('0.', '') + new Date().getTime()) * 16 | 0,
            v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

因此,注意到这篇文章有超过30个答案,这里是...... 这篇文章有:一个“TL;DR”代码部分w/自含的es6类 Xuid一个使用案例和动机讨论部分关于es6类 Xuid提供代码。

class Xuid {
  //@ edges.sm.st, ess.dev: MIT license Smallscript/David Simmons 2020
  //! Can't use `static const field = const` xbrowser (thus, const's duped)
  static get v4New() {
    const ns7Now = this.ns7Now, xnode48 = this.xnode48; let clock_seq13
    // monotonic `clock_seq` guarantee (13-bits/time-quantum)
    if(ns7Now <= this.ns7Now_prevSeq && this.ns7Now_prevSeq)
      clock_seq13 = ((this.ns7Now_prevSeq += 1n) - ns7Now) & 0b1_1111_1111_1111n
    else
      clock_seq13 = 0n, this.ns7Now_prevSeq = ns7Now
    const time60 = ((ns7Now << 4n) & 0xFFFF_FFFF_FFFF_0000n) |
                           (ns7Now & 0x0000_0000_0000_0FFFn),
              v4 = 0x1_00000000_0000_0000_0000_000000000000n |
      (time60 << 64n) | (0x00000000_0000_4000_0000_000000000000n) | // M: V4
      (0b110n << 61n) | (clock_seq13 << 48n) | // N: Variant-2 time-seq collation
      xnode48, s = v4.toString(16)//.substr(1)
    return `{${s.substr(1,8)}-${s.substr(9,4)}-${s.substr(13,4)}-${
      s.substr(17,4)}-${s.substr(21,12)}}`
  }
  static get xnode48()/*:<BigInt#48>*/{
    if(this.xnode48_) return this.xnode48_
    let clockSeqNode; if(typeof URL !== 'undefined' && URL.createObjectURL) {
      const url = URL.createObjectURL(new Blob())
      const id = (url.toString().split('/').reverse()[0]).split('-')
      URL.revokeObjectURL(url)
      clockSeqNode = BigInt('0x'+id[3]+id[4])
    }
    else {
      const a4 = this.a4; this.getRandomValues(this.a4);
      clockSeqNode = (BigInt(a4[2]) << 32n) | BigInt(a4[3])
    }
    // simulate the 48-bit node-id and 13-bit clock-seq
    // to combine with 3-bit uuid-variant
    return this.xnode48_ = clockSeqNode & 0xFFFF_FFFF_FFFFn;
  }
  static get jdNow()/*:<double#ns7>*/{
    // return 2440587.5+Date.now()/864e5 // <- Date-quantum-ms form (7ns form below)
    return this.jdFromNs7(this.ns7Now)
  }
  static get ns7Now()/*:<BigInt#60>*/{
    if(typeof performance !== 'undefined' && performance.now)
      Reflect.defineProperty(this, 'ns7Now',
        Reflect.getOwnPropertyDescriptor(this,'ns7Now_performance'))
    else
      Reflect.defineProperty(this, 'ns7Now',
        Reflect.getOwnPropertyDescriptor(this, 'ns7Now_Date'))
    return this.ns7Now
  }
  static get ns7Now_Date()/*:<BigInt#60>*/{
    // const epoch1582Ns7_bias = 0x1b2_1dd2_1381_4000  // V1 1582 Oct 15
    // const epoch1601Ns7_bias = 0x19d_b1de_d53e_8000n // FILETIME base
    const epoch1970Ns7 = BigInt(Date.now() * 1000_0.0)
    return epoch1970Ns7 + 0x1b2_1dd2_1381_4000n
  }
  static get ns7Now_performance()/*:<BigInt#60>*/{
    const epochPgNs7 = BigInt(performance.now()*/*15*/1000_0.0|/*17*/0)
    if(!this.epoch1970PgNs7) // performance.timing.navigationStart
      this.epoch1970PgNs7 = this.ns7Now_Date - epochPgNs7
    return epochPgNs7 + this.epoch1970PgNs7
  }
  static dateFromJd(jd) {return new Date((jd - 2440587.5) * 864e5)}
  static dateFromNs7(ns7) {
    return new Date(Number(ns7 - 0x1b2_1dd2_1381_4000n) / 1000_0.0)}
  static jdFromNs7(ns7) {   // atomic-clock leap-seconds (ignored)
    return 2440587.5 + (Number(ns7 - 0x1b2_1dd2_1381_4000n) / 864e9)
  }
  static ns7FromJd(jd) {
    return BigInt((jd - 2440587.5) * 864e9) + 0x1b2_1dd2_1381_4000n
  }
  static getRandomValues(va/*:<Uint32Array>*/) {
    if(typeof crypto !== 'undefined' && crypto.getRandomValues)
      crypto.getRandomValues(va)
    else for(let i = 0, n = va.length; i < n; i += 1)
      va[i] = Math.random() * 0x1_0000_0000 >>> 0
  }
  static get a4() {return this.a4_ || (this.a4_ = new Uint32Array(4))}
  static ntohl(v)/*:<BigInt>*/{
    let r = '0x', sign = 1n, s = BigInt(v).toString(16)
    if(s[0] == '-') s = s.substr(1), sign = -1n
    for(let i = s.length; i > 0; i -= 2)
      r += (i == 1) ? ('0' + s[i-1]) : s[i-2] + s[i-1]
    return sign*BigInt(r)
  }
  static ntohl32(v)/*:<Number>*/{return Number(this.ntohl(v))}
}

总结

雖然有,但我希望這對現在有足夠的解釋;試試。

在GitHub上发布 EdgeS Web-Client Eswc 图书馆的一部分时, indexedDb 使用模式与 efs 将作为其设计意图的示例,其中包括处理效率和可用性与 indexedDb 和相关 PWA 同步和复制场景。

Related

朱利安日计算在JavaScript中

基准评分 Novids/sec

const start = Xuid.ns7Now
for(let i = 100000; i; i -=1)
  Xuid.v4New
const end = Xuid.ns7Now
console.log(`Delta 7ns: ${(end-start)/100000n}`)

使用:

let uniqueId = Date.now().toString(36) + Math.random().toString(36).substring(2);

document.getElementById(“独一无二”。innerHTML = Math.random().toString(36).substring(2) + (新日期()).getTime().toString(36); <div id="unique"> </div>

您可以通过添加更多数字来增加这个数字,但要创建100%独特的ID,您将需要使用全球计数器。

let u = Date.now().toString(16) + Math.random().toString(16) + '0'.repeat(16);
let guid = [u.substr(0,8), u.substr(8,4), '4000-8' + u.substr(13,3), u.substr(16,12)].join('-');

let u = Date.now().toString(16)+Math.random().toString(16)+'0'.repeat(16); let guid = [u.substr(0,8), u.substr(8,4), '4000-8' + u.substr(13,3), u.substr(16,12)].join('-'); document.getElementById("unique").innerHTML = guid; <div id="unique"> </div>