5489

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.

11

77 Answers77

5758
+50

[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.

Sign up to request clarification or add additional context in comments.

15 Comments

Surely the answer to @Muxa's question is 'no'? It's never truly safe to trust something that came from the client. I guess it depends on how likely your users are to bring up a javascript console and manually change the variable so to something they want. Or they could just POST you back the id that they want. It would also depend on whether the user picking their own ID is going to cause vulnerabilities. Either way, if it's a random number ID that's going into a table, I would probably be generating it server-side, so that I know I have control over the process.
@DrewNoakes - UUIDs aren't just a string of completely random #'s. The "4" is the uuid version (4 = "random"). The "y" marks where the uuid variant (field layout, basically) needs to be embedded. See sections 4.1.1 and 4.1.3 ofietf.org/rfc/rfc4122.txt for more info.
im a bit confused, in javascript[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
Typescript users: you can add<any> right before the first array, like this:<any>[1e7] - quick way to get it to pass.
I like the custom solution, except for the expression[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.
|
2642

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 asMath.random)

Thus, developers writing code for production environments are encouraged to use a rigorous, well-maintained implementation such as theuuid module.

14 Comments

Actually, the RFC allows for UUIDs that are created from random numbers. You just have to twiddle a couple of bits to identify it as such. See section 4.4. Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers:rfc-archive.org/getrfc.php?rfc=4122
This should not be the accepted answer. It does not actually answer the question - instead encouraging the import of 25,000 lines of code for something you can do with one line of code in any modern browser.
@AbhiBeckert the answer is from 2008 and for node.js projects it might be valid to choose a dependency more over project size
@Phil this is a "highly active question", which means it should have an excellent answer with a green tick. Unfortunately that's not the case. There is nothing wrong or incorrect with this answer (if there was, I'd edit the answer) - but another far better answer exists below and I think it should be at the top of the list. Also the question is specifically relating to javascript in a browser, not node.js.
I challenge the claim that Math.random is that low of a quality of randomness.v8.dev/blog/math-random. As you can see, it's passes a good test suite, and the same algorithm is used by v8, FF and Safari. And the RFC states, pseudo-random numbers are acceptable for UUIDs
|
1031

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>

Here's a fiddle to test.


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

Bear in mind,new Date().getTime() is not updated every millisecond. I'm not sure how this affects the expected randomness of your algorithm.
performance.now would be even better. Unlike Date.now, the timestamps returned byperformance.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.
The actual time resolution may or may not be 17 ms (1/60 second), not 1 ms.
WouldCrypto.getRandomValues fix the main problems with Math.random??
@NaveenReddyMarthala Node.js by default runs JavaScript in strict mode, which unfortunately doesn't allow boolean logic operators to shorthand check the truthiness ofundefined 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.
|
564

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

This code still contains a couple of errors: theMath.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.
Can I just say -- I cannot count how many times I've pointed devs to this answer because it so beautifully points out the tradeoffs between performance, code-elegance, and readability. Thank you Jeff.
I don't know if @Broofa's answer has changed since these tests were run (or if the browser engines running the tests have changed - it has been five years), but I just ran them both on two different benchmarking services (jsben.ch and jsbench.github.io), and in each case Broofa's answer (using Math.random) was faster than this e7() version by 30 - 35%.
@Andy is right. Broofa's code is faster as of Aug 2021. I implemented Dave's suggestions and ran the test myself. But I don't imagine the difference should matter all that much in production:jsbench.github.io/#80610cde9bc93d0f3068e5793e60ff11
@bedalton: Why would we compare broofa's answer to "the e4 version"? The "4" in e4 simply refers to the iteration of optimization and not to the version of UUID, right?
|
233

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

This is not UUID though?
Relaying on MAC addresses for uniqueness on virtual machines is a bad idea!
I do something like this, but with leading characters and some dashes (e.g[slug, date, random].join("_") to createusr_1dcn27itd_hj6onj6phr. It makes it so the id also doubles as a "created at" field
Building on @SephReed's comment, I think having the date part first is nice since it sorts chronologically, which may provide benefits later if storing or indexing the IDs.
For those wondering:toString(36) converts in a base-36 numeration (0..9a..z). Example:(35).toString(36) isz.
|
195

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

You should declare the array size beforehand rather than sizing it dynamically as you build the GUID.var s = new Array(36);
I think there's a very minor bug in the line that sets bits bits 6-7 of the clock_seq_hi_and_reserved to 01. Since s[19] is a character '0'..'f' and not an int 0x0..0xf, (s[19] & 0x3) | 0x8 will not be randomly distributed -- it will tend to produce more '9's and fewer 'b's. This only makes a difference if you care about the random distribution for some reason.
107

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:

  • TheMath.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 get0.6fb7687f).Math.random().toString(16).
  • Then we cut off the0. prefix (0.6fb7687f =>6fb7687f) and get a string with eight hexadecimalcharacters long.(Math.random().toString(16).substr(2,8).
  • Sometimes theMath.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 theMath.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 formatXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.
  • I divided the GUID into four pieces, each piece divided into two types (or formats):XXXXXXXX and-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), thes parameter 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.

Link to this post on my blog

Enjoy! :-)

5 Comments

This implementation is incorrect. Certain characters of the GUID require special treatment (e.g. the 13th digit needs to be the number 4).
Slightly rewritten, with fat arrow functions and toStr(depricated) -> toString. Also removed the hyphens! guid = () => { _p8 = () => {return (Math.random() * 10000000000).toString(16).substr(0,8);} return${_p8()}${_p8()}${_p8()}${_p8()}; };
@JLRishe 13th digit should not be always number 4, it represents the UUID version. It can be 3,4,5.. depending on the version
@AshishSingh Version 4 is the only one that's based entirely on random number generation. The other versions involve hashing and seed values of various types. Since this answer ostensibly produces randomly generated UUIDs, the most logical choice for the 13th digit should be 4. At any rate, the 13th digit shouldn't be randomly generated, which is what this answer is doing, and that was my main point.
@JLRishe thanks for that info though, I was not aware that random is based only on version 4
87

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.2s

Here is the timing code.

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

1 Comment

Not sure if implementations have changed in the last 10 years, but Math.random() doesn't produce as many digits for me as it seems to produce for you -- there are only 10 or 11 characters in Math.random().toString(36).substring(2, 15) for me.
81

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

Note that this isn't a GUID in the technical sense, because it does nothing to guarantee uniqueness. That may or may not matter depending on your application.
A quick note about performance. This solution creates 36 strings total to get a single result. If performance is critical, consider creating an array and joining as recommended by:tinyurl.com/y37xtx Further research indicates it may not matter, so YMMV:tinyurl.com/3l7945
Regarding uniqueness, it's worth noting that version 1,3, and 5 UUIDs are deterministic in ways version 4 isn't. If the inputs to these uuid generators - node id in v1, namespace and name in v3 and v5 - are unique (as they're supposed to be), then the resulting UUIDs be unique. In theory, anyway.
These GUIDs are invalid because they don't specify version and variant required by the ITU-T | ISO recommendation.
@DanielMarschall, this doesn't produce UUIDs, but does produce valid GUIDs which were common place in Microsoft code (e.g. .Net) in 2008 when this answer was written. Note, that this is also why the hex characters are forced to upper case. See:learn.microsoft.com/en-us/windows/win32/msi/guid
|
72

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

note that the first version, the one ` window.crypto.getRandomValues, 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.
67

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

60

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

Alternativelywindow.URL.createObjectURL(new Blob([])).split('/').pop() will do the same without having to rely on external factors like URL length.
What is "Blob"/"Blobs"?
Umm this most definitely does not work. To work reliably on different domains, it needs to be changed to something likewindow.URL.createObjectURL(new Blob([])).substr(-36)
What's the drawback of this solution?
Better to replace substr with slice in the compact solution.URL.createObjectURL(new Blob([])).slice(-36)
|
57

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 uuid

Or 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

Note: These imports didn't work for me. Import statements have changed, as stated in the repo:const { v4: uuidv4 } = require('uuid'); and ES6:import { v4 as uuidv4 } from 'uuid';
40

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-51012f947136

Comments

40
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

37

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

What is bothering aboutall answers is that it seemsok for JavaScript to store theGUID as astring. Your answer at least tackles themuch more efficient storage using aUint16Array. ThetoString function should be using the binary representation in an JavaScriptobject
This UUIDs produced by this code are either weak-but-RFC-compliant (_guid), or strong-but-not-RFC-compliant (_cryptoGuid). The former uses Math.random(), which is now known to be a poor RNG. The latter is failing to set the version and variant fields.
@broofa - What would you suggest to make it strongand RFC-compliant? And why is _cryptoGuid not RFC-compliant?
@Matt _cryptoGuid() sets all 128 bits randomly, meaning it doesn't set the version and variant fields as described in the RFC. See my alternate implementation of uuidv4() that uses crypto.getRandomValues() in my top-voted answer, above, for a strong+compliant implementation.
37

Added 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

And Safari is coming as well!
29

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

27

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

24
  // 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

18

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

17

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

This is readable code, thank you. IMO the accepted answer has too complicated code, but this instead is understandable.
16

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

Thank you for detailed description! Specifically nibble caged between 8 and 11 with equivalents explanation is super helpful.
16

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

works like a charm. Better than trying to generate manually. Very clever!
The performance is quite worst, but depending on the case it can be enough
For the fastest combined generator that is compliant w/node-clock-seq, monotonic in time, etc. This forms a good basis to seed auuid4 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.
Is the inclusion of a UUID here guaranteed, or is it just something that the current browser implementations all happen to do?
@M.Justin It's guaranteed -- you can followw3c.github.io/FileAPI/#dfn-createObjectURL to where it is specified, quoting, "Generate a UUID [RFC4122] as a string and append it to result".
15

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

An explanation would be in order. E.g., what ES6 features does it use that previous answers don't? Please respond byediting your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
15

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

13

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

BTW, why does it generate only numbers and not characters as well? much less secure
you can also add characters (letters ) like this:Array.from((window.crypto || window.msCrypto).getRandomValues(new Uint32Array(4))).map(n => n.toString(16)).join('-')
12

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

Well most of the js devs are web developers, and we won't understand what bitwise operators do, because we don't use them most of the times we develop. Actually I never needed any of them, and I am a js dev since '97. So your example code is still totally unreadable to the average web developer who will read it. Not to mention that you still use single letter variable names, which makes it even more cryptic. Probably read Clean Code, maybe that helps:amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/…
@inf3rno don't bash him, all the proposed solutions in this thread are cryptic but they are correct answers considering the question was to have a one-liner of sorts. that's what one-liners are cryptic. they can't afford to be readable to the average developer but they save screen real estate where a simple preceding comment will do. And as a result, ends up being much more readable that way then if it had been in "readable code" instead.
@user1529413 Yes. Uniqueness requires an index.
This is my favourite answer, because it's building a UUID as a 16-byte (128 bit) value, and not its serialized, nice to read form. It'd be trivially easy to drop the string stuff and just set the correct bits of a random 128bit, which is all a uuidv4 needs to be. You could base64 it for shorter URLs, pass it back to some webassembly, store it in less memory space than as a string, make it a 4096-size buffer and put 256 uuids in it, store in a browser db, etc. Much better than having everything as a long, lowercase hex-encoded string from the start.
12

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

Why is it better?
12

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

The redirected URL says"Applies to: SharePoint Foundation 2010"
Protected question. To answer this question, you need to have at least 10 reputation on this site (not counting theassociation bonus). The reputation requirement helps protect this question from spam and non-answer activity.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.