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

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


当前回答

下面是顶级投票答案的组合,与Chrome的冲突工作组合:

generateGUID = (typeof(window.crypto) != 'undefined' &&
                typeof(window.crypto.getRandomValues) != 'undefined') ?
    function() {
        // If we have a cryptographically secure PRNG, use that
        // https://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript
        var buf = new Uint16Array(8);
        window.crypto.getRandomValues(buf);
        var S4 = function(num) {
            var ret = num.toString(16);
            while(ret.length < 4){
                ret = "0"+ret;
            }
            return ret;
        };
        return (S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));
    }

    :

    function() {
        // Otherwise, just use Math.random
        // https://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
            return v.toString(16);
        });
    };

这是在Jsbin,如果你想测试它。

其他回答

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 页面。

这里是一个完全不符合但非常有效的实施,以产生一个ASCII安全的GUID类似的独特识别器。

function generateQuickGuid() {
    return Math.random().toString(36).substring(2, 15) +
        Math.random().toString(36).substring(2, 15);
}

创建 26 个字符 [a-z0-9],产生一个 UID 既较短又比 RFC 符合的 GUID 更独特。

这里是这个功能的使用例子和时间表,以及这个问题的其他几个答案。

>>> generateQuickGuid()
"nvcjf1hs7tf8yyk4lmlijqkuo9"
"yq6gipxqta4kui8z05tgh9qeel"
"36dh5sec7zdj90sk2rx7pjswi2"
runtime: 32.5s

>>> GUID() // John Millikin
"7a342ca2-e79f-528e-6302-8f901b0b6888"
runtime: 57.8s

>>> regexGuid() // broofa
"396e0c46-09e4-4b19-97db-bd423774a4b3"
runtime: 91.2s

>>> createUUID() // Kevin Hakanson
"403aa1ab-9f70-44ec-bc08-5d5ac56bd8a5"
runtime: 65.9s

>>> UUIDv4() // Jed Schmidt
"f4d7d31f-fa83-431a-b30c-3e6cc37cc6ee"
runtime: 282.4s

>>> Math.uuid() // broofa
"5BD52F55-E68F-40FC-93C2-90EE069CE545"
runtime: 225.8s

>>> Math.uuidFast() // broofa
"6CB97A68-23A2-473E-B75B-11263781BBE6"
runtime: 92.0s

>>> Math.uuidCompact() // broofa
"3d7b7a06-0a67-4b67-825c-e5c43ff8c1e8"
runtime: 229.0s

>>> bitwiseGUID() // jablko
"baeaa2f-7587-4ff1-af23-eeab3e92"
runtime: 79.6s

>>>> betterWayGUID() // Andrea Turri
"383585b0-9753-498d-99c3-416582e9662c"
runtime: 60.0s

>>>> UUID() // John Fowler
"855f997b-4369-4cdb-b7c9-7142ceaf39e8"
runtime: 62.2s

这里是时间代码。

var r;
console.time('t'); 
for (var i = 0; i < 10000000; i++) { 
    r = FuncToTest(); 
};
console.timeEnd('t');

根據 RFC 4122 的 UUID (Universally Unique IDentifier),也被稱為 GUID (Globally Unique IDentifier),是為提供某些獨特性保證而設計的識別。

虽然可以在JavaScript代码的几个行中实施符合RFC的UUID(例如,请参见 @broofa的答案,下面),但有几个常见的漏洞:

无效 ID 格式(UUID 必须是“xxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx”的格式,其中 x 是 [0-9, a-f] M 是 [1-5] 的格式,而 N 是 [8, 9, a 或 b] 使用低质量的随机性来源(如 Math.random)

因此,开发人员为生产环境编写代码被鼓励使用严格,良好的实施,如新模块。

這裡是一個工作例子. 它生成一個 32 位數的獨特 UUID。

function generateUUID() {
    var d = new Date();
    var k = d.getTime();
    var str = k.toString(16).slice(1)
    var UUID = 'xxxx-xxxx-4xxx-yxxx-xzx'.replace(/[xy]/g, function (c)
    {
        var r = Math.random() * 16 | 0;
        v = c == 'x' ? r : (r & 3 | 8);
        return v.toString(16);
    });

    var newString = UUID.replace(/[z]/, str)
    return newString;
}

var x = generateUUID()
console.log(x, x.length)

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

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