在JavaScript中创建GUID / UUID?
我正在尝试在JavaScript中创建全局唯一标识符。我不确定所有浏览器上都提供哪些例程,内置随机数生成器的"随机性"和种子状态如何,等等。
GUID / UUID至少应包含32个字符,并且应保持在ASCII范围内,以免在传递它们时遇到麻烦。
解决方案
已经对此进行了几次尝试。问题是:我们要使用实际的GUID,还是只需要看起来像GUID的随机数?生成随机数很容易。
function guid() { function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); }
但是,请注意,这些值不是真正的GUID。
注意:提供的代码段不遵循RFC4122,这要求版本(4
)必须集成到生成的输出字符串中。如果我们需要兼容的GUID,请不要使用此答案。
使用:
var uuid = guid();
function guid() { return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); } function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } document.getElementById('jsGenId').addEventListener('click', function() { document.getElementById('jsIdResult').value = guid(); })
input { font-family: monospace; }
<button id="jsGenId" type="button">Generate GUID</button> <br> <input id="jsIdResult" type="text" placeholder="Results will be placed here..." readonly size="40"/>
来自sagi shkedy的技术博客:
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生成器可以保证唯一键(请参阅Wikipedia文章)。总是有碰撞的机会。 GUID仅提供足够大的键范围,以将冲突的变化减少到几乎为零。
Web服务将很有用。
快速的Google找到了:http://www.hoskinson.net/GuidGenerator/
无法保证该实现,但SOMEONE必须发布真实的GUID生成器。
使用这种Web服务,我们可以开发一个REST Web界面,该界面使用GUID Web服务,并通过AJAX将其提供给浏览器中的javascript。
从好的OL维基百科开始,有指向UUID的javascript实现的链接。
它看起来相当优雅,也许可以通过对客户端IP地址的哈希值加盐来进行改进。此哈希可能可以插入到html文档服务器端,以供客户端javascript使用。
更新:原始站点已改组,这是更新的版本
这是一些基于RFC 4122,第4.4节(根据真正随机数或者伪随机数创建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; }
此创建版本4 UUID(从伪随机数创建):
function uuid() { var chars = '0123456789abcdef'.split(''); var uuid = [], rnd = Math.random, r; uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'; uuid[14] = '4'; // version 4 for (var i = 0; i < 36; i++) { if (!uuid[i]) { r = 0 | rnd()*16; uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf]; } } return uuid.join(''); }
这是生成的UUID的示例:
682db637-0f31-4847-9cdf-25ba9613a75c 97d19478-3ab2-4aa1-b8cc-a1c3540f54aa 2eed04c9-2692-456d-a0fd-51012f947136
对于符合RFC4122版本4的解决方案,此一站式解决方案是我能想到的最紧凑的解决方案。
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。有关详细信息,请参见Adam Hyland在Math.random()上的出色文章。对于更强大的解决方案,请考虑使用uuid模块[免责声明:我是作者]之类的东西,该模块会在可用时使用更高质量的RNG API。
更新,2015-08-26:作为旁注,本要点描述了如何确定在达到一定的碰撞概率之前可以生成多少个ID。例如,使用3.26x1015版本4 RFC4122 UUID,我们有百万分之一的碰撞机会。
更新,2017-06-28:Chrome开发人员的一篇好文章,讨论了Chrome,Firefox和Safari中Math.random PRNG的质量状态。 tl; dr截至2015年末,它的"相当好",但没有加密质量。为了解决这个问题,这是上述解决方案的更新版本,该解决方案使用ES6,crypto
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());
这只是一个简单的AJAX调用...
如果仍然有人感兴趣,这是我的解决方案。
在服务器端:
[WebMethod()] public static string GenerateGuid() { return Guid.NewGuid().ToString(); }
在客户端:
var myNewGuid = null; PageMethods.GenerateGuid( function(result, userContext, methodName) { myNewGuid = result; }, function() { alert("WebService call failed."); } );
// 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('-');