javascript - 在JavaScript中,创建guid/uuid?

我正在尝试在JavaScript中创建全局唯一标识符,

guid/uuid应该至少为32个字符,并且应该在ASCII范围内,以避免在传递它们时出现麻烦。

时间:

对于 RFC4122 4兼容解决方案,这个one-liner(ish)解决方案是我可以想到的最紧凑的解决方案:

 

function uuidv4() {


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


 });


}



console.log(uuidv4())

更新,2015-06-02:请注意,UUID唯一性在很大程度上依赖于底层随机数生成器(RNG)。上面的解决方案使用Math.random()来简化,但是,Math.random()不能保证是高质量的RNG。要获得更强大的解决方案,请考虑类似于uuid模块[免责声明:

更新,2015-08-26:作为旁注,这个要点描述了如何确定在达到一定的碰撞概率之前可以生成多少个ID。例如,使用3.26 x1015版本4 RFC4122 UUID,您有一个百万分之一的碰撞机会。

更新,2017-06-28:Chrome开发人员在Chrome,Firefox和Safari中讨论Math.random PRNG质量状态的好文章。tl; dr - 截至2015年底,它"非常好",但是,这指的不是加密质量。为了解决这个问题,这里是上述解决方案的更新版本,它使用ES6,加密API和一些JS向导,我不提供质量保证:

 

function uuidv4() {


 return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>


 (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15> > c/4).toString(16)


 )


}



console.log(uuidv4());

下面是类似的 RFC4122版本4兼容解决方案,通过将前13个十六进制数字通过时间戳的十六进制部分偏移来解决这个问题,这样,即使Math.random在同一种种子上,两个客户端都必须在相同的毫秒(或10,000年后)上生成UUID才能获得相同的UUID:

 

function generateUUID() {//Public Domain/MIT


 var d = new Date().getTime();


 if (typeof performance!== 'undefined' && typeof performance.now === 'function'){


 d += performance.now();//use high-precision timer if available


 }


 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {


 var r = (d + Math.random() * 16) % 16 | 0;


 d = Math.floor(d/16);


 return (c === 'x'? r : (r & 0x3 | 0x8)).toString(16);


 });


}




在这里的很容易测试。

下面是一些基于 RFC 4122的代码,节4.4 (从真正随机或 Pseudo-Random数字创建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;


}



 

var uniqueId = Math.random().toString(36).substring(2) 


 + (new Date()).getTime().toString(36);



 

document.getElementById(" unique" ).innerHTML =


 Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36);
 

<div id= "unique"> 


</div>

如果生成的ID超过1毫秒,则它们为100%唯一。

如果以较短的间隔生成两个ID,并且假设随机方法是真正随机的,那么,这将生成99.999 99999999999%可能是全局唯一的ID(在10 ^ 1中的碰撞) 15),

您可以通过添加更多数字来增加此数字,但是,要生成100%唯一ID ,您将需要使用全局计数器。

如果确实需要RFC合规性,此格式将作为有效的版本4GUID传递:

 

var u = (new Date()).getTime().toString(16) + 


 Math.random().toString(16).substring(2) +" 0" .repeat(16);


var guid = u.substr(0,8) + '-' + u.substr(8,4) + '-4000-8' + 


 u.substr(12,3) + '-' + u.substr(15,12);



 

var u = (new Date()).getTime().toString(16) + 


 Math.random().toString(16).substring(2) +" 0" .repeat(16);


var guid = u.substr(0,8) + '-' + u.substr(8,4) + '-4000-8' + 


 u.substr(12,3) + '-' + u.substr(15,12);


document.getElementById(" unique" ).innerHTML = guid;
 

<div id= "unique"> 


</div>

编辑:above代码遵循强度,但是,不遵循RFC的字母,除其他差异之外,它是几个随机数字,(如果需要,就添加更多随机数字)的好处是,与 100%兼容代码相比,这是非常快的,你可以在这里对你的GUID进行测试

下面是最高投票的组合,用于解决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上的

下面是一个完全不兼容,但是,性能非常高的实现来生成ASCII-safe GUID-like唯一标识符。

 

function generateQuickGuid() {


 return Math.random().toString(36).substring(2, 15) +


 Math.random().toString(36).substring(2, 15);


}



生成26个[a-z0-9]字符,生成一个UID,它比符合的GUIDs更短且更独特,如果人类可读性很重要,可以简单地添加破折号。

下面是这个函数的用法示例和计时,以及其中一些问题答案,在Chrome m25下,每个迭代都执行了10次迭代。

 

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



来自shkedy博客的 Sagi技术:

 

function generateGuid() {


 var result, i, j;


 result = '';


 for(j=0; j<32; j++) {


 if( j == 8 || j == 12 || j == 16 || j == 20) 


 result = result + '-';


 i = Math.floor(Math.random()*16).toString(16).toUpperCase();


 result = result + i;


 }


 return result;


}



还有其他方法涉及使用ActiveX控件,但是,请远离这些方法!

编辑:我认为有必要指出没有GUID生成器可以保证唯一的键(查看维基百科文章),总是有碰撞的机会,GUID只提供足够大的键,以便将碰撞的变化减少到几乎为零。

...