I'm trying to create globally-unique identifiers in JavaScript. I'm not sure what routines are available on all browsers, how "random" and seeded the built-in random number generator is, etc.
The GUID / UUID should be at least 32 characters and should stay in the ASCII range to avoid trouble when passing them around.
For an RFC4122 version 4 compliant solution, this one-liner(ish) solution is the most compact I could come up with:
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
console.log(uuidv4());
Update, 2015-06-02: Be aware that UUID uniqueness relies heavily on the underlying random number generator (RNG). The solution above uses Math.random()
for brevity, however Math.random()
is not guaranteed to be a high-quality RNG. See Adam Hyland's excellent writeup on Math.random() for details. For a more robust solution, consider using the uuid module, which uses higher quality RNG APIs.
Update, 2015-08-26: As a side-note, this gist describes how to determine how many IDs can be generated before reaching a certain probability of collision. For example, with 3.26x1015 version 4 RFC4122 UUIDs you have a 1-in-a-million chance of collision.
Update, 2017-06-28: A good article from Chrome developers discussing the state of Math.random
PRNG quality in Chrome, Firefox, and Safari. tl;dr - As of late-2015 it's "pretty good", but not cryptographic quality. To address that issue, here's an updated version of the above solution that uses ES6, the crypto
API, and a bit of JavaScript wizardry I can't take credit for:
function uuidv4() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
console.log(uuidv4());
Update, 2020-01-06: There is a proposal in the works for a standard uuid
module as part of the JavaScript language