41

I have a script that, when a user loads, creates a unique id. Which is then saved in localStorage and used for tracking transactions. Sort of like using a cookie, except since the browser is generating the unique id there might be collisions when sent to the server. Right now I'm using the following code:

function genID() {
    return Math.random().toString(36).substr(2)
        + Math.random().toString(36).substr(2)
        + Math.random().toString(36).substr(2)
        + Math.random().toString(36).substr(2);
}

I realize this is a super basic implementation, and want some feedback on better ways to create a "more random" id that will prevent collisions on the server. Any ideas?

Trevor Norris
  • 20,499
  • 4
  • 26
  • 28
  • does javascript have GUID? – Sam I am says Reinstate Monica Mar 08 '13 at 16:17
  • @SamIam phpjs, underscore, and i'm sure many more libraries have a uniqueId function, but JS does not provide one natively – SgtPooki Feb 26 '14 at 14:43
  • @TrevNorris Were you actually running into conflicts with that? How many entries did you have? I created a simple test to determine how many Math.random().toString(34).substr(2)'s it took to create a duplicate, and with web workers my script ran for a few hours without creating a conflict. (toString(36) is shorter and still has 7.30787211e+9 different permutations) – SgtPooki Feb 26 '14 at 14:49
  • 2
    @SgtPooki I'd never run into a conflict. Just wanted to know if there was a Right Way to do uid's in JS. – Trevor Norris Feb 27 '14 at 18:55
  • @TrevNorris thanks for the confirmation, I wanted to make sure I didn't need to go back and fix something... =P – SgtPooki Mar 05 '14 at 20:28

1 Answers1

19

I've used this in the past. Collision odds should be very low.

var generateUid = function (separator) {
    /// <summary>
    ///    Creates a unique id for identification purposes.
    /// </summary>
    /// <param name="separator" type="String" optional="true">
    /// The optional separator for grouping the generated segmants: default "-".    
    /// </param>

    var delim = separator || "-";

    function S4() {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }

    return (S4() + S4() + delim + S4() + delim + S4() + delim + S4() + delim + S4() + S4() + S4());
};
James South
  • 10,147
  • 4
  • 59
  • 115
  • 2
    I like the way you constrained the random value length. – Trevor Norris Aug 31 '12 at 23:28
  • 1
    @James South, I did not exactly get it..can you explain? – Venkatesh Laguduva Jan 28 '13 at 14:57
  • 1
    What does the '0x10000' do? – Jack Jan 06 '16 at 09:51
  • It's 65536, the largest 16bit number https://en.wikipedia.org/wiki/65536_(number) – James South Jan 06 '16 at 10:25
  • Little suggestion: I found others samples using a call to getTime() to limit the risks of collisions... var generateUid = function (separator) { var delim = separator || "-"; function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } var st = ((new Date).getTime().toString(16)).slice(0,11) + (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1,2); return (S4() + S4() + delim + S4() + delim + S4() + delim + S4() + delim + st); }; – Didier68 Oct 19 '16 at 07:46
  • @JackNicholson 0x10000 = 65536 – hakki Jul 25 '19 at 16:39
  • function random() { return btoa( JSON.stringify({ time: Date.now(), uid: Math.round(Math.random() * 1000000000) }) ); } – Malik Bagwala Mar 17 '20 at 11:44
  • Using Arrows => https://stackoverflow.com/a/75855405/3057246 – Vinod Srivastav Mar 31 '23 at 12:29