How do I create GUIDs (globally-unique identifiers) in JavaScript? The GUID / UUID should be at least 32 characters and should stay in the ASCII range to avoid trouble when passing them around.
I'm not sure what routines are available on all browsers, how "random" and seeded the built-in random number generator is, etc.
- 41GUIDs when repesented as as strings are at least 36 and no more than 38 characters in length and match the pattern ^\{?[a-zA-Z0-9]{36}?\}$ and hence are always ascii.AnthonyWJones– AnthonyWJones2008-09-19 20:35:06 +00:00CommentedSep 19, 2008 at 20:35
- 5David Bau provides a much better, seedable random number generator atdavidbau.com/archives/2010/01/30/… I wrote up a slightly different approach to generating UUIDs atblogs.cozi.com/tech/2010/04/generating-uuids-in-javascript.htmlGeorge V. Reilly– George V. Reilly2010-05-04 23:09:46 +00:00CommentedMay 4, 2010 at 23:09
- 1Weird that no one has mentioned this yet but for completeness, there's a plethora ofguid generators on npm I'm willing to bet most of them work in browser too.George Mauer– George Mauer2014-02-03 15:54:16 +00:00CommentedFeb 3, 2014 at 15:54
- 2Some 12 years later with
BigIntand ES6 classes, other techniques that yield rates of 500,000 uuid/sec can be done.See referencesmallscript– smallscript2020-12-30 06:34:38 +00:00CommentedDec 30, 2020 at 6:34 - 7Asothershavementioned, if you're only generating a small number of uuids in a browser, just use
URL.createObjectURL(new Blob()).substr(-36). (Excellent browser support, too). (To avoid memory leakage,call URL.revokeObjectURL(url))rinogo– rinogo2021-10-21 02:47:27 +00:00CommentedOct 21, 2021 at 2:47
77 Answers77
[Edited 2023-03-05 to reflect latest best-practices for producing RFC4122-compliant UUIDs]
crypto.randomUUID() is now standard on all modern browsers and JS runtimes. However, becausenew browser APIs are restricted to secure contexts, this method is only available to pages served locally (localhost or127.0.0.1) or over HTTPS.
For readers interested in other UUID versions, generating UUIDs on legacy platforms or in non-secure contexts, there istheuuid module. It is well-tested and supported.
Failing the above, there is this method (based on the original answer to this question):
function uuidv4() { return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => (+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16) );}console.log(uuidv4());Note:The use ofany UUID generator that relies onMath.random() is strongly discouraged (including snippets featured in previous versions of this answer) forreasons best explained here.TL;DR: solutions based onMath.random() do not provide good uniqueness guarantees.
15 Comments
[1e7]+-1e3 does not really mean anything, an array is added to a number? what am I missing? note: in typescript it does not pass<any> right before the first array, like this:<any>[1e7] - quick way to get it to pass.[1e7]+-1e3+-4e3+-8e3+-1e11 in it. I personally prefer the expression`${1e7}-${1e3}-${4e3}-${8e3}-${1e11}` instead. It's somewhat longer, but also somewhat clearer to me. And it allows me to easily change the generated UUID's format as well.UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDentifier), according toRFC 4122, are identifiers designed to provide certain uniqueness guarantees.
While it is possible to implement RFC-compliant UUIDs in a few lines of JavaScript code (e.g., see@broofa's answer, below) there are several common pitfalls:
- Invalid id format (UUIDs must be of the form "
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx", where x is one of [0-9, a-f]M is one of [1-5], andN is [8, 9, a, or b] - Use of a low-quality source of randomness (such as
Math.random)
Thus, developers writing code for production environments are encouraged to use a rigorous, well-maintained implementation such as theuuid module.
14 Comments
I really like how cleanBroofa's answer is, but it's unfortunate thatpoor implementations ofMath.random leave the chance for collision.
Here's a similarRFC4122 version 4 compliant solution that solves that issue by offsetting the first 13 hex numbers by a hex portion of the timestamp, and once depleted offsets by a hex portion of the microseconds since pageload. That way, even ifMath.random is on the same seed, both clients would have to generate the UUID the exact same number of microseconds since pageload (if high-perfomance time is supported) AND at the exact same millisecond (or 10,000+ years later) to get the same UUID:
function generateUUID() { // Public Domain/MIT var d = new Date().getTime();//Timestamp var d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now()*1000)) || 0;//Time in microseconds since page-load or 0 if unsupported return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random() * 16;//random number between 0 and 16 if(d > 0){//Use timestamp until depleted r = (d + r)%16 | 0; d = Math.floor(d/16); } else {//Use microseconds since page-load if supported r = (d2 + r)%16 | 0; d2 = Math.floor(d2/16); } return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); });}var onClick = function(){ document.getElementById('uuid').textContent = generateUUID();}onClick();#uuid { font-family: monospace; font-size: 1.5em; }<p></p><button>Generate UUID</button>Modernized snippet for ES6
const generateUUID = () => { let d = new Date().getTime(), d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0; return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { let r = Math.random() * 16; if (d > 0) { r = (d + r) % 16 | 0; d = Math.floor(d / 16); } else { r = (d2 + r) % 16 | 0; d2 = Math.floor(d2 / 16); } return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); });};const onClick = (e) => document.getElementById('uuid').textContent = generateUUID();document.getElementById('generateUUID').addEventListener('click', onClick);onClick();#uuid { font-family: monospace; font-size: 1.5em; }<p></p><button>Generate UUID</button>12 Comments
new Date().getTime() is not updated every millisecond. I'm not sure how this affects the expected randomness of your algorithm.performance.now() are not limited to one-millisecond resolution. Instead, they represent times as floating-point numbers with up tomicrosecond precision. Also unlike Date.now, the values returned by performance.now()always increase at a constant rate, independent of the system clock which might be adjusted manually or skewed by software such as the Network Time Protocol.undefined variables. To fix this, try replacingvar d2 = (performance .. withvar d2 = (typeof performance !== 'undefined' .. as in the update version. The other option (which will actually utilize the enhanced precision of performance with Node.js rather than throwing it away) is to re-addconst { performance } = require('perf_hooks'); in your requirements.broofa's answer is pretty slick, indeed - impressively clever, really... RFC4122 compliant, somewhat readable, and compact. Awesome!
But if you're looking at that regular expression, those manyreplace() callbacks,toString()'s andMath.random() function calls (where he's only using four bits of the result and wasting the rest), you may start to wonder about performance. Indeed, joelpt even decided to toss out an RFC for generic GUID speed withgenerateQuickGUID.
But, can we get speedand RFC compliance? I say, YES! Can we maintain readability? Well... Not really, but it's easy if you follow along.
But first, my results, compared to broofa,guid (the accepted answer), and the non-rfc-compliantgenerateQuickGuid:
Desktop Android broofa: 1617ms 12869ms e1: 636ms 5778ms e2: 606ms 4754ms e3: 364ms 3003ms e4: 329ms 2015ms e5: 147ms 1156ms e6: 146ms 1035ms e7: 105ms 726ms guid: 962ms 10762msgenerateQuickGuid: 292ms 2961ms - Note: 500k iterations, results will vary by browser/CPU.So by my 6th iteration of optimizations, I beat the most popular answer by over12 times, the accepted answer by over9 times, and the fast-non-compliant answer by2-3 times. And I'm still RFC 4122 compliant.
Interested in how? I've put the full source onhttp://jsfiddle.net/jcward/7hyaC/3/ and onhttps://jsben.ch/xczxS
For an explanation, let's start with broofa's code:
function broofa() { 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(broofa())So it replacesx with any random hexadecimal digit,y with random data (except forcing the top two bits to10 per the RFC spec), and the regex doesn't match the- or4 characters, so he doesn't have to deal with them. Very, very slick.
The first thing to know is that function calls are expensive, as are regular expressions (though he only uses 1, it has 32 callbacks, one for each match, and in each of the 32 callbacks it calls Math.random() and v.toString(16)).
The first step toward performance is to eliminate the RegEx and its callback functions and use a simple loop instead. This means we have to deal with the- and4 characters whereas broofa did not. Also, note that we can use String Array indexing to keep his slick String template architecture:
function e1() { var u='',i=0; while(i++<36) { var c='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'[i-1],r=Math.random()*16|0,v=c=='x'?r:(r&0x3|0x8); u+=(c=='-'||c=='4')?c:v.toString(16) } return u;}console.log(e1())Basically, the same inner logic, except we check for- or4, and using a while loop (instead ofreplace() callbacks) gets us an almost 3X improvement!
The next step is a small one on the desktop but makes a decent difference on mobile. Let's make fewer Math.random() calls and utilize all those random bits instead of throwing 87% of them away with a random buffer that gets shifted out each iteration. Let's also move that template definition out of the loop, just in case it helps:
function e2() { var u='',m='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',i=0,rb=Math.random()*0xffffffff|0; while(i++<36) { var c=m[i-1],r=rb&0xf,v=c=='x'?r:(r&0x3|0x8); u+=(c=='-'||c=='4')?c:v.toString(16);rb=i%8==0?Math.random()*0xffffffff|0:rb>>4 } return u}console.log(e2())This saves us 10-30% depending on platform. Not bad. But the next big step gets rid of the toString function calls altogether with an optimization classic - the look-up table. A simple 16-element lookup table will perform the job of toString(16) in much less time:
function e3() { var h='0123456789abcdef'; var k='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'; /* same as e4() below */}function e4() { var h=['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']; var k=['x','x','x','x','x','x','x','x','-','x','x','x','x','-','4','x','x','x','-','y','x','x','x','-','x','x','x','x','x','x','x','x','x','x','x','x']; var u='',i=0,rb=Math.random()*0xffffffff|0; while(i++<36) { var c=k[i-1],r=rb&0xf,v=c=='x'?r:(r&0x3|0x8); u+=(c=='-'||c=='4')?c:h[v];rb=i%8==0?Math.random()*0xffffffff|0:rb>>4 } return u}console.log(e4())The next optimization is another classic. Since we're only handling four bits of output in each loop iteration, let's cut the number of loops in half and process eight bits in each iteration. This is tricky since we still have to handle the RFC compliant bit positions, but it's not too hard. We then have to make a larger lookup table (16x16, or 256) to store 0x00 - 0xFF, and we build it only once, outside the e5() function.
var lut = []; for (var i=0; i<256; i++) { lut[i] = (i<16?'0':'')+(i).toString(16); }function e5() { var k=['x','x','x','x','-','x','x','-','4','x','-','y','x','-','x','x','x','x','x','x']; var u='',i=0,rb=Math.random()*0xffffffff|0; while(i++<20) { var c=k[i-1],r=rb&0xff,v=c=='x'?r:(c=='y'?(r&0x3f|0x80):(r&0xf|0x40)); u+=(c=='-')?c:lut[v];rb=i%4==0?Math.random()*0xffffffff|0:rb>>8 } return u}console.log(e5())I tried an e6() that processes 16-bits at a time, still using the 256-elementLUT, and it showed the diminishing returns of optimization. Though it had fewer iterations, the inner logic was complicated by the increased processing, and it performed the same on desktop, and only ~10% faster on mobile.
The final optimization technique to apply - unroll the loop. Since we're looping a fixed number of times, we can technically write this all out by hand. I tried this once with a single random variable,r, that I kept reassigning, and performance tanked. But with four variables assigned random data up front, then using the lookup table, and applying the proper RFC bits, this version smokes them all:
var lut = []; for (var i=0; i<256; i++) { lut[i] = (i<16?'0':'')+(i).toString(16); }function e7(){ var d0 = Math.random()*0xffffffff|0; var d1 = Math.random()*0xffffffff|0; var d2 = Math.random()*0xffffffff|0; var d3 = Math.random()*0xffffffff|0; return lut[d0&0xff]+lut[d0>>8&0xff]+lut[d0>>16&0xff]+lut[d0>>24&0xff]+'-'+ lut[d1&0xff]+lut[d1>>8&0xff]+'-'+lut[d1>>16&0x0f|0x40]+lut[d1>>24&0xff]+'-'+ lut[d2&0x3f|0x80]+lut[d2>>8&0xff]+'-'+lut[d2>>16&0xff]+lut[d2>>24&0xff]+ lut[d3&0xff]+lut[d3>>8&0xff]+lut[d3>>16&0xff]+lut[d3>>24&0xff];}console.log(e7())Modualized:http://jcward.com/UUID.js -UUID.generate()
The funny thing is, generating 16 bytes of random data is the easy part. The whole trick is expressing it instring format with RFC compliance, and it's most tightly accomplished with 16 bytes of random data, an unrolled loop and lookup table.
I hope my logic is correct -- it's very easy to make a mistake in this kind of tedious bit work. But the outputs look good to me. I hope you enjoyed this mad ride through code optimization!
Be advised: my primary goal was to show and teach potential optimization strategies. Other answers cover important topics such as collisions and truly random numbers, which are important for generating good UUIDs.
8 Comments
Math.random()*0xFFFFFFFF lines should beMath.random()*0x100000000 for full randomness, and>>>0 should be used instead of|0 to keep the values unsigned (though with the current code I think it gets away OK even though they are signed). Finally it would be a very good idea these days to usewindow.crypto.getRandomValues if available, and fall-back to Math.random only if absolutely necessary. Math.random may well have less than 128 bits of entropy, in which case this would be more vulnerable to collisions than necessary.Use:
let uniqueId = Date.now().toString(36) + Math.random().toString(36).substring(2);document.getElementById("unique").innerHTML = Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36);<div></div>If IDs are generated more than 1 millisecond apart, they are 100% unique.
If two IDs are generated at shorter intervals, and assuming that the random method is truly random, this would generate IDs that are 99.99999999999999% likely to be globally unique (collision in 1 of 10^15).
You can increase this number by adding more digits, but to generate 100% unique IDs you will need to use a global counter.
If you need RFC compatibility, this formatting will pass as a valid version 4 GUID:
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></div>The above code follow the intention, but not the letter of the RFC. Among other discrepancies it's a few random digits short. (Add more random digits if you need it) The upside is that this is really fast :)You cantest validity of your GUID here
10 Comments
[slug, date, random].join("_") to createusr_1dcn27itd_hj6onj6phr. It makes it so the id also doubles as a "created at" fieldtoString(36) converts in a base-36 numeration (0..9a..z). Example:(35).toString(36) isz.Here's some code based onRFC 4122, section 4.4 (Algorithms for Creating a UUID from Truly Random or Pseudo-Random Number).
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;}2 Comments
var s = new Array(36);This is the fastest GUID-like string generator method in the formatXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. It does not generate a standard-compliant GUID.
Ten million executions of this implementation take just 32.5 seconds, which is the fastest I've ever seen in a browser (the only solution without loops/iterations).
The function is as simple as:
/** * Generates a GUID string. * @returns {string} The generated GUID. * @example af8a8416-6e18-a307-bd9c-f2c947bbb3aa * @author Slavik Meltser. * @link http://slavik.meltser.info/?p=142 */function guid() { function _p8(s) { var p = (Math.random().toString(16)+"000000000").substr(2,8); return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ; } return _p8() + _p8(true) + _p8(true) + _p8();}To test the performance, you can run this code:
console.time('t');for (var i = 0; i < 10000000; i++) { guid();};console.timeEnd('t');I'm sure most of you will understand what I did there, but maybe there is at least one person that will need an explanation:
The algorithm:
- The
Math.random()function returns a decimal number between 0 and 1 with 16 digits after the decimal fraction point (forexample0.4363923368509859). - Then we take this number and convertit to a string with base 16 (from the example above we'll get
0.6fb7687f).Math.random().toString(16). - Then we cut off the
0.prefix (0.6fb7687f=>6fb7687f) and get a string with eight hexadecimalcharacters long.(Math.random().toString(16).substr(2,8). - Sometimes the
Math.random()function will returnshorter number (for example0.4363), due to zeros at the end (from the example above, actually the number is0.4363000000000000). That's why I'm appending to this string"000000000"(a string with nine zeros) and then cutting it off withsubstr()function to make it nine characters exactly (filling zeros to the right). - The reason for adding exactly nine zeros is because of the worse case scenario, which is when the
Math.random()function will return exactly 0 or 1 (probability of 1/10^16 for each one of them). That's why we needed to add nine zeros to it ("0"+"000000000"or"1"+"000000000"), and then cutting it off from the second index (third character) with a length of eight characters. For the rest of the cases, the addition of zeros will not harm the result because it is cutting it off anyway.Math.random().toString(16)+"000000000").substr(2,8).
The assembly:
- The GUID is in the following format
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. - I divided the GUID into four pieces, each piece divided into two types (or formats):
XXXXXXXXand-XXXX-XXXX. - Now I'm building the GUID using these two types to assemble the GUID with call four pieces, as follows:
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. - To differ between these two types, I added a flag parameter to a pair creator function
_p8(s), thesparameter tells the function whether to add dashes or not. - Eventually we build the GUID with the following chaining:
_p8() + _p8(true) + _p8(true) + _p8(), and return it.
Enjoy! :-)
5 Comments
${_p8()}${_p8()}${_p8()}${_p8()}; };Here is a totally non-compliant but very performant implementation to generate an ASCII-safe GUID-like unique identifier.
function generateQuickGuid() { return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);}Generates 26 [a-z0-9] characters, yielding a UID that is both shorter and more unique than RFC compliant GUIDs. Dashes can be trivially added if human-readability matters.
Here are usage examples and timings for this function and several of this question's other answers. The timing was performed under Chrome m25, 10 million iterations each.
>>> 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.2sHere is the timing code.
var r;console.time('t'); for (var i = 0; i < 10000000; i++) { r = FuncToTest(); };console.timeEnd('t');1 Comment
Fromsagi shkedy's technical blog:
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;}There are other methods that involve using anActiveX control, but stay away from these!
I thought it was worth pointing out that no GUID generator can guarantee unique keys (check theWikipedia article). There is always a chance of collisions. A GUID simply offers a large enough universe of keys to reduce the change of collisions to almost nil.
8 Comments
Here is a combination of thetop voted answer, with a workaround forChrome's collisions:
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); }); };It ison jsbin if you want to test it.
1 Comment
, does not keep the Version 4 UUIDs format defined by RFC 4122. That is instead ofxxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx` it yieldsxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.Here's a solution dated Oct. 9, 2011 from a comment by userjed athttps://gist.github.com/982883:
UUIDv4 = function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)}This accomplishes the same goal as thecurrent highest-rated answer, but in 50+ fewer bytes by exploiting coercion, recursion, and exponential notation. For those curious how it works, here's the annotated form of an older version of the function:
UUIDv4 =function b( a // placeholder){ return a // if the placeholder was passed, return ? ( // a random number from 0 to 15 a ^ // unless b is 8, Math.random() // in which case * 16 // a random number from >> a/4 // 8 to 11 ).toString(16) // in hexadecimal : ( // or otherwise a concatenated string: [1e7] + // 10000000 + -1e3 + // -1000 + -4e3 + // -4000 + -8e3 + // -80000000 + -1e11 // -100000000000, ).replace( // replacing /[018]/g, // zeroes, ones, and eights with b // random hex digits )}Comments
One line solution using Blobs.
window.URL.createObjectURL(new Blob([])).substring(31);The value at the end (31) depends on the length of the URL.
EDIT:
A more compact and universal solution, as suggested byrinogo:
URL.createObjectURL(new Blob([])).slice(-36);11 Comments
window.URL.createObjectURL(new Blob([])).split('/').pop() will do the same without having to rely on external factors like URL length.window.URL.createObjectURL(new Blob([])).substr(-36)URL.createObjectURL(new Blob([])).slice(-36)You can usenode-uuid. It provides simple, fast generation ofRFC4122 UUIDS.
Features:
- Generate RFC4122 version 1 or version 4 UUIDs
- Runs inNode.js and browsers.
- Cryptographically strong random # generation on supporting platforms.
- Small footprint (Want something smaller?Check this out!)
Install Using NPM:
npm install uuidOr using uuid via a browser:
Download Raw File (uuid v1):https://raw.githubusercontent.com/kelektiv/node-uuid/master/v1.jsDownload Raw File (uuid v4):https://raw.githubusercontent.com/kelektiv/node-uuid/master/v4.js
Want even smaller? Check this out:https://gist.github.com/jed/982883
Usage:
// Generate a v1 UUID (time-based)const uuidV1 = require('uuid/v1');uuidV1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'// Generate a v4 UUID (random)const uuidV4 = require('uuid/v4');uuidV4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'// Generate a v5 UUID (namespace)const uuidV5 = require('uuid/v5');// ... using predefined DNS namespace (for domain names)uuidV5('hello.example.com', v5.DNS)); // -> 'fdda765f-fc57-5604-a269-52a7df8164ec'// ... using predefined URL namespace (for, well, URLs)uuidV5('http://example.com/hello', v5.URL); // -> '3bbcee75-cecc-5b56-8031-b6641c1ed1f1'// ... using a custom namespaceconst MY_NAMESPACE = '(previously generated unique uuid string)';uuidV5('hello', MY_NAMESPACE); // -> '90123e1c-7512-523e-bb28-76fab9f2f73d'ECMAScript 2015 (ES6):
import uuid from 'uuid/v4';const id = uuid();1 Comment
const { v4: uuidv4 } = require('uuid'); and ES6:import { v4 as uuidv4 } from 'uuid';This creates a version 4 UUID (created from pseudo random numbers):
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('');}Here is a sample of the UUIDs generated:
682db637-0f31-4847-9cdf-25ba9613a75c97d19478-3ab2-4aa1-b8cc-a1c3540f54aa2eed04c9-2692-456d-a0fd-51012f947136Comments
var uuid = function() { var buf = new Uint32Array(4); window.crypto.getRandomValues(buf); var idx = -1; return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { idx++; var r = (buf[idx>>3] >> ((idx%8)*4))&15; var v = c == 'x' ? r : (r&0x3|0x8); return v.toString(16); });};This version is based on Briguy37's answer and some bitwise operators to extract nibble sized windows from the buffer.
It should adhere to the RFC Type 4 (random) schema, since I hadproblems last time parsing non-compliant UUIDs with Java's UUID.
Comments
Simple JavaScript module as a combination of best answers in this question.
var crypto = window.crypto || window.msCrypto || null; // IE11 fixvar Guid = Guid || (function() { var EMPTY = '00000000-0000-0000-0000-000000000000'; var _padLeft = function(paddingString, width, replacementChar) { return paddingString.length >= width ? paddingString : _padLeft(replacementChar + paddingString, width, replacementChar || ' '); }; var _s4 = function(number) { var hexadecimalResult = number.toString(16); return _padLeft(hexadecimalResult, 4, '0'); }; var _cryptoGuid = function() { var buffer = new window.Uint16Array(8); crypto.getRandomValues(buffer); return [_s4(buffer[0]) + _s4(buffer[1]), _s4(buffer[2]), _s4(buffer[3]), _s4(buffer[4]), _s4(buffer[5]) + _s4(buffer[6]) + _s4(buffer[7])].join('-'); }; var _guid = function() { var currentDateMilliseconds = new Date().getTime(); return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(currentChar) { var randomChar = (currentDateMilliseconds + Math.random() * 16) % 16 | 0; currentDateMilliseconds = Math.floor(currentDateMilliseconds / 16); return (currentChar === 'x' ? randomChar : (randomChar & 0x7 | 0x8)).toString(16); }); }; var create = function() { var hasCrypto = crypto != 'undefined' && crypto !== null, hasRandomValues = typeof(window.crypto.getRandomValues) != 'undefined'; return (hasCrypto && hasRandomValues) ? _cryptoGuid() : _guid(); }; return { newGuid: create, empty: EMPTY };})();// DEMO: Create and show GUIDconsole.log('1. New Guid: ' + Guid.newGuid());// DEMO: Show empty GUIDconsole.log('2. Empty Guid: ' + Guid.empty);Usage:
Guid.newGuid()
"c6c2d12f-d76b-5739-e551-07e6de5b0807"
Guid.empty
"00000000-0000-0000-0000-000000000000"
4 Comments
GUID as astring. Your answer at least tackles themuch more efficient storage using aUint16Array. ThetoString function should be using the binary representation in an JavaScriptobjectAdded in: v15.6.0, v14.17.0 there is a built-incrypto.randomUUID() function.
import { randomUUID } from "node:crypto";const uuid = crypto.randomUUID();In the browser,crypto.randomUUID() is currently supported in Chromium 92+ and Firefox 95+.
1 Comment
The version below is an adaptation ofbroofa's answer, but updated to include a "true" random function that uses crypto libraries where available, and the Alea() function as a fallback.
Math.log2 = Math.log2 || function(n){ return Math.log(n) / Math.log(2); } Math.trueRandom = (function() { var crypt = window.crypto || window.msCrypto; if (crypt && crypt.getRandomValues) { // If we have a crypto library, use it var random = function(min, max) { var rval = 0; var range = max - min; if (range < 2) { return min; } var bits_needed = Math.ceil(Math.log2(range)); if (bits_needed > 53) { throw new Exception("We cannot generate numbers larger than 53 bits."); } var bytes_needed = Math.ceil(bits_needed / 8); var mask = Math.pow(2, bits_needed) - 1; // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111 // Create byte array and fill with N random numbers var byteArray = new Uint8Array(bytes_needed); crypt.getRandomValues(byteArray); var p = (bytes_needed - 1) * 8; for(var i = 0; i < bytes_needed; i++ ) { rval += byteArray[i] * Math.pow(2, p); p -= 8; } // Use & to apply the mask and reduce the number of recursive lookups rval = rval & mask; if (rval >= range) { // Integer out of acceptable range return random(min, max); } // Return an integer that falls within the range return min + rval; } return function() { var r = random(0, 1000000000) / 1000000000; return r; }; } else { // From https://web.archive.org/web/20120502223108/http://baagoe.com/en/RandomMusings/javascript/ // Johannes Baagøe <[email protected]>, 2010 function Mash() { var n = 0xefc8249d; var mash = function(data) { data = data.toString(); for (var i = 0; i < data.length; i++) { n += data.charCodeAt(i); var h = 0.02519603282416938 * n; n = h >>> 0; h -= n; h *= n; n = h >>> 0; h -= n; n += h * 0x100000000; // 2^32 } return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 }; mash.version = 'Mash 0.9'; return mash; } // From http://baagoe.com/en/RandomMusings/javascript/ function Alea() { return (function(args) { // Johannes Baagøe <[email protected]>, 2010 var s0 = 0; var s1 = 0; var s2 = 0; var c = 1; if (args.length == 0) { args = [+new Date()]; } var mash = Mash(); s0 = mash(' '); s1 = mash(' '); s2 = mash(' '); for (var i = 0; i < args.length; i++) { s0 -= mash(args[i]); if (s0 < 0) { s0 += 1; } s1 -= mash(args[i]); if (s1 < 0) { s1 += 1; } s2 -= mash(args[i]); if (s2 < 0) { s2 += 1; } } mash = null; var random = function() { var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 s0 = s1; s1 = s2; return s2 = t - (c = t | 0); }; random.uint32 = function() { return random() * 0x100000000; // 2^32 }; random.fract53 = function() { return random() + (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53 }; random.version = 'Alea 0.9'; random.args = args; return random; }(Array.prototype.slice.call(arguments))); }; return Alea(); }}());Math.guid = function() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.trueRandom() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); });};Comments
JavaScript project on GitHub -https://github.com/LiosK/UUID.js
UUID.js The RFC-compliant UUID generator for JavaScript.
See RFC 4122http://www.ietf.org/rfc/rfc4122.txt.
Features Generates RFC 4122 compliant UUIDs.
Version 4 UUIDs (UUIDs from random numbers) and version 1 UUIDs (time-based UUIDs) are available.
UUID object allows a variety of access to the UUID including access to the UUID fields.
Low timestamp resolution of JavaScript is compensated by random numbers.
Comments
// 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('-');Comments
For those wanting anRFC 4122 version 4 compliant solution with speed considerations (few calls to Math.random()):
var rand = Math.random;function UUID() { var nbr, randStr = ""; do { randStr += (nbr = rand()).toString(16).substr(3, 6); } while (randStr.length < 30); return ( randStr.substr(0, 8) + "-" + randStr.substr(8, 4) + "-4" + randStr.substr(12, 3) + "-" + ((nbr*4|0)+8).toString(16) + // [89ab] randStr.substr(15, 3) + "-" + randStr.substr(18, 12) );}console.log( UUID() );The above function should have a decent balance between speed and randomness.
Comments
I couldn't find any answer that uses a single 16-octetTypedArray and aDataView, so I think the following solution for generating a version 4 UUID perthe RFC will stand on its own here:
const uuid4 = () => { const data = crypto.getRandomValues(new Uint8Array(16)); /// Fill a new 16-byte (128 bits) buffer with random bits data[6] = (data[6] & 0xf) | 0x40; /// Patch the 6th byte [of the buffer] to reflect a version 4 UUID data[8] = (data[8] & 0x3f) | 0x80; /// Patch the 8th byte [of the buffer] to reflect a variant 1 UUID (version 4 UUIDs are) const view = new DataView(data.buffer); /// Create a view backed by the buffer (for accessing the data as words etc) 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 of the data};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`; e.g. `ho(13, 2)` returns `"0d"`I prefer it because:
- it only relies on API(s) available to the standard ECMAScript platform, where possible -- which is all but one API (
crypto) - it only uses a single buffer, minimizing copying of data, which should in theory yield performance advantage
At the time of writing this,getRandomValues is not something implemented for thecrypto object in specificallyNode.js. However, it has the equivalentrandomBytes function which may be used instead.
1 Comment
I wanted to understandbroofa's answer, so I expanded it and added comments:
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); } );};1 Comment
The nativeURL.createObjectURL is generating an UUID. You can take advantage of this.
function uuid() { const url = URL.createObjectURL(new Blob()) const [id] = url.toString().split('/').reverse() URL.revokeObjectURL(url) return id}5 Comments
uuid4 generator w/60-bits of epoch70 μ-seconds of monotonic time, 4-bit uuid-version, and 48-bit node-id and 13-bit clock-seq with 3-bit uuid-variant. --<br> Combining usingBigInt to writentohl and related conversion this works very fast with thelut approach here. --<br> I can provide code if desired.ES6 sample
const guid=()=> { const s4=()=> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4() + s4() + s4()}`;}1 Comment
I adjusted my own UUID/GUID generator with some extrashere.
I'm usingthe following Kybos random number generator to be a bit more cryptographically sound.
Below is my script with the Mash and Kybos methods from baagoe.com excluded.
//UUID/Guid Generator// use: UUID.create() or UUID.createSequential()// convenience: UUID.empty, UUID.tryParse(string)(function(w){ // From http://baagoe.com/en/RandomMusings/javascript/ // Johannes Baagøe <[email protected]>, 2010 //function Mash() {...}; // From http://baagoe.com/en/RandomMusings/javascript/ //function Kybos() {...}; var rnd = Kybos(); //UUID/GUID Implementation from http://frugalcoder.us/post/2012/01/13/javascript-guid-uuid-generator.aspx var UUID = { "empty": "00000000-0000-0000-0000-000000000000" ,"parse": function(input) { var ret = input.toString().trim().toLowerCase().replace(/^[\s\r\n]+|[\{\}]|[\s\r\n]+$/g, ""); if ((/[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}/).test(ret)) return ret; else throw new Error("Unable to parse UUID"); } ,"createSequential": function() { var ret = new Date().valueOf().toString(16).replace("-","") for (;ret.length < 12; ret = "0" + ret); ret = ret.substr(ret.length-12,12); //only least significant part for (;ret.length < 32;ret += Math.floor(rnd() * 0xffffffff).toString(16)); return [ret.substr(0,8), ret.substr(8,4), "4" + ret.substr(12,3), "89AB"[Math.floor(Math.random()*4)] + ret.substr(16,3), ret.substr(20,12)].join("-"); } ,"create": function() { var ret = ""; for (;ret.length < 32;ret += Math.floor(rnd() * 0xffffffff).toString(16)); return [ret.substr(0,8), ret.substr(8,4), "4" + ret.substr(12,3), "89AB"[Math.floor(Math.random()*4)] + ret.substr(16,3), ret.substr(20,12)].join("-"); } ,"random": function() { return rnd(); } ,"tryParse": function(input) { try { return UUID.parse(input); } catch(ex) { return UUID.empty; } } }; UUID["new"] = UUID.create; w.UUID = w.Guid = UUID;}(window || this));Comments
If you just need a random 128 bit string in no particular format, you can use:
function uuid() { return crypto.getRandomValues(new Uint32Array(4)).join('-');}Which will return something like2350143528-4164020887-938913176-2513998651.
2 Comments
Array.from((window.crypto || window.msCrypto).getRandomValues(new Uint32Array(4))).map(n => n.toString(16)).join('-')Just another more readable variant with just two mutations.
function uuid4(){ function hex (s, b) { return s + (b >>> 4 ).toString (16) + // high nibble (b & 0b1111).toString (16); // low nibble } let r = crypto.getRandomValues (new Uint8Array (16)); r[6] = r[6] >>> 4 | 0b01000000; // Set type 4: 0100 r[8] = r[8] >>> 3 | 0b10000000; // Set variant: 100 return r.slice ( 0, 4).reduce (hex, '' ) + r.slice ( 4, 6).reduce (hex, '-') + r.slice ( 6, 8).reduce (hex, '-') + r.slice ( 8, 10).reduce (hex, '-') + r.slice (10, 16).reduce (hex, '-');}4 Comments
The better way:
function( a, b // Placeholders){ for( // Loop :) b = a = ''; // b - result , a - numeric variable a++ < 36; // b += a*51&52 // If "a" is not 9 or 14 or 19 or 24 ? // return a random number or 4 ( a^15 // If "a" is not 15, ? // generate a random number from 0 to 15 8^Math.random() * (a^20 ? 16 : 4) // unless "a" is 20, in which case a random number from 8 to 11, : 4 // otherwise 4 ).toString(16) : '-' // In other cases, (if "a" is 9,14,19,24) insert "-" ); return b }Minimized:
function(a,b){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'-');return b}1 Comment
If your environment is SharePoint, there is a utility function calledSP.Guid.newGuid (MSDN link which creates a new GUID. This function is inside the sp.init.js file. If you rewrite this function (to remove some other dependencies from other private functions), and it looks like this:
var newGuid = function () { var result = ''; var hexcodes = "0123456789abcdef".split(""); for (var index = 0; index < 32; index++) { var value = Math.floor(Math.random() * 16); switch (index) { case 8: result += '-'; break; case 12: value = 4; result += '-'; break; case 16: value = value & 3 | 8; result += '-'; break; case 20: result += '-'; break; } result += hexcodes[value]; } return result;};1 Comment
Explore related questions
See similar questions with these tags.




























