Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ID - a unique ID/name generator for JavaScript
// Generate unique IDs for use as pseudo-private/protected names.
// Similar in concept to
// <http://wiki.ecmascript.org/doku.php?id=strawman:names>.
//
// The goals of this function are twofold:
//
// * Provide a way to generate a string guaranteed to be unique when compared
// to other strings generated by this function.
// * Make the string complex enough that it is highly unlikely to be
// accidentally duplicated by hand (this is key if you're using `ID`
// as a private/protected name on an object).
//
// Use:
//
// var privateName = ID();
// var o = { 'public': 'foo' };
// o[privateName] = 'bar';
var ID = function () {
// Math.random should be unique because of its seeding algorithm.
// Convert it to base 36 (numbers + letters), and grab the first 9 characters
// after the decimal.
return '_' + Math.random().toString(36).substr(2, 9);
};
@JustMikey

This comment has been minimized.

Copy link

commented Feb 20, 2014

Thank you, it was helpful :)

@themesociety

This comment has been minimized.

Copy link

commented Feb 21, 2014

Thanks, working great. :)

@carlosocarvalho

This comment has been minimized.

Copy link

commented Feb 26, 2014

Thank you.

@niklas-r

This comment has been minimized.

Copy link

commented Mar 7, 2014

This doesn't always match /_\w{9}/ and I'm not sure why. If someone could help me understand why that is I'd be grateful.

@ezakto

This comment has been minimized.

Copy link

commented May 12, 2014

@nikias-r
Sometimes .toString() returns a string representation with length shorter than 9. ie:

var number = Math.random() // 0.9394456857981651
number.toString(36); // '0.xtis06h6'
var id = number.toString(36).substr(2, 9); // 'xtis06h6'
id.length >= 9; // false

This doesn't happen in all browsers (this example can be replicated in firefox, but not in chrome).

@javestruz

This comment has been minimized.

Copy link

commented May 30, 2014

Thanks!

@ksaitor

This comment has been minimized.

Copy link

commented Jul 8, 2014

Thank you! 👍

@yairsz

This comment has been minimized.

Copy link

commented Feb 25, 2015

Excelent! Thank you!

@vcostin

This comment has been minimized.

Copy link

commented Jun 19, 2015

Thanks!

@ravinsinghd

This comment has been minimized.

Copy link

commented Jun 23, 2015

Thanks

@jhclaura

This comment has been minimized.

Copy link

commented Jul 19, 2015

Works great! Thank!

@mkpenrod05

This comment has been minimized.

Copy link

commented Nov 7, 2015

Simple and sweet, thanks!

@alexmorleyfinch

This comment has been minimized.

Copy link

commented Nov 11, 2015

This is okay for generating less than 10 thousand unique IDs, but any more than 10 thousand and you are going to run into collisions.

I wrote a simple function to check for duplicates:

function checkDuplicates(generator, count){
  var hash = {};
  var dupe = [];
  for(var idx = 0; idx < count; ++idx){
    var gen = generator(idx); // generate our unique ID

    // if it already exists, then it has been duplicated
    if(typeof hash[gen] != 'undefined'){
      dupe.push({
        duplicate: gen,
        indexCreated: hash[gen],
        indexDuplicated: idx,
        duplicateCount: dupe.filter(function(cur){return cur.duplicate == gen}).length,
      });
    }
    hash[gen] = idx;
  }
  return dupe;
}

This function returns an array of duplicates. The format of a returned duplicate is as follows:

duplicate = {
  duplicate: "7srx2zt3zj2lnmi", // the generated id that was duplicated
  duplicateCount: 0,            // 0 is the first duplication, so 1 is the second duplication etc
  indexCreated: 133959,         // the index where the original ID was created
  indexDuplicated: 168948,      // the index where the original ID is duplicated
}

All you need to do is pass a function that returns your generated unique IDs, and the number of times you want to generate. The function is used like so:

function myUniqueID(){
  return Math.random().toString(36).slice(2);
}

checkDuplicates(myUniqueID, Math.pow(10, 4)); // Math.pow(10, 4) == 10'000 times

Calling the above returns an empty array. This means that no duplicates were found for less than 10 thousand iterations.

It you keep calling this, you keep getting 0 duplications. However, if you change the number of iterations to 100 thousand (or Math.pow(10, 5)), then you get between 0 and 3 duplicates. Change to 1 million and you get more than 100 duplicates. Change it to 10 million and you'll get thousands of duplicates.

Also, if you change it to 10 million you start to get multiple copies of duplicates! The same generated ID is not only duplicated once, but sometimes many times! If you run the following code, it will show you which keys were duplicated more than once (it may take a minute):

var duplicates = checkDuplicates(myUniqueID, Math.pow(10, 7)) // 10 MILLION

// now only show the duplicates that have a `duplicateCount` of more than 1
// (meaning they have been duplicated for a second time)
duplicates.filter(function(cur){
  return cur.duplicateCount > 0
});

When I run it with 10 million iterations, we get over 10 thousand duplicates, 10 of which have been duplicated twice

So as we can see, this function is okay for less than 10 thousand IDs, but any more and you are likely to run into collisions.

Therefore, do not use this to generate unique IDs. There are much better ways to do it.

However, a simple fix to get a lot less collisions would be to append the current time (new Date).getTime() to the returned ID. However, this still gets a few collisions when checking duplications for 10 million (still better than thousands)

Just out of interest, I found this function. It also uses Math.random, however it uses it multiple times, effectively reducing the chance that Math.random will generate the same numbers in the same order. It outputs a string in the format of a UUID (Universally Unique IDentifier).

function uniqueID(){
  function chr4(){
    return Math.random().toString(16).slice(-4);
  }
  return chr4() + chr4() +
    '-' + chr4() +
    '-' + chr4() +
    '-' + chr4() +
    '-' + chr4() + chr4() + chr4();
}

uniqueID() // "e27881c4-f924-b8f7-59d9-525878c7a812"

// NOTE: This format of 8 chars, followed by 3 groups of 4 chars, followed by 12 chars
//       is known as a UUID and is defined in RFC4122 and is a standard for generating unique IDs.
//       This function DOES NOT implement this standard. It simply outputs a string
//       that looks similar. The standard is found here: https://www.ietf.org/rfc/rfc4122.txt

If you call checkDuplicates with this, you will see that even with 10 million generations (or Math.pow(10, 7)) a collision is not detected, so this appears pretty safe.

I tried to run Math.pow(10, 8) which is 100 million, but it took forever and never finished. You may want to run your own tests for more than 100 million

@marcosschlup

This comment has been minimized.

Copy link

commented Mar 3, 2016

For unique you can use Date.now() plus a random:

(Date.now().toString(36) + Math.random().toString(36).substr(2, 5)).toUpperCase()

@abdulhannanali

This comment has been minimized.

Copy link

commented Mar 4, 2016

@marcosschlup How are you sure it'll be a random unique id?

@huang-xiao-jian

This comment has been minimized.

Copy link

commented Apr 1, 2016

thanks, very helpful

@mniak

This comment has been minimized.

Copy link

commented Jun 22, 2016

Really good

@natsimhan

This comment has been minimized.

Copy link

commented Jul 1, 2016

Excellent solution alexmorleyfinch ;) And thx author for original id ;)

@iddan

This comment has been minimized.

Copy link

commented Jul 21, 2016

Using it all the time! thank you

@hegwin

This comment has been minimized.

Copy link

commented Sep 20, 2016

So cool. Thanks.

@mzhda

This comment has been minimized.

Copy link

commented Oct 15, 2016

this is helpful

@MichaelDimitras

This comment has been minimized.

Copy link

commented Oct 18, 2016

Thanks a lot alexmorleyfinch. This was really informative.

@devboxr

This comment has been minimized.

Copy link

commented Jun 16, 2017

I'm writing this in the hopes that others may find this on Google.

I had an issue that I'm using a v-for in Vue.js on a component, but in Vue 2.2+ you required :key to be set with a unique identifier. In my case the Array that it iterates over doesn't have any, so I had to generate one on demand (imagine a Bootstrap alerts manager component, e.g.). This will do just fine.

#vuejs #v-for

@hackeronline7

This comment has been minimized.

Copy link

commented Jun 25, 2017

Thanks!

@balaarunreddyv1

This comment has been minimized.

Copy link

commented Jun 28, 2017

Thanks

@iatsiuk

This comment has been minimized.

Copy link

commented Jul 25, 2017

@devboxr :key must be unique inside the v-for loop, not for the entire vue component. in your case array has an index and that is enough

@up209d

This comment has been minimized.

Copy link

commented Jul 26, 2017

I think the first one still the best, if you don't want it run into a collision just make one more

'-' + Math.random().toString(36).substr(2, 9) + '-' + Math.random().toString(36).substr(2, 9)

@beenotung

This comment has been minimized.

Copy link

commented Aug 21, 2017

@devboxr iatsiuk's suggestion is more simple, for fun or other cases, you can get a unique id (without randomness) in a pretty effective way just by counting (Thanks to Javascript's single thread limitation).

You may take a reference on this demo:

export interface Counter {
  next(): number;
}

export function new_counter(init = 0): Counter {
  return {
    next: () => ++init
  };
}

export const Counter = new_counter(1);
@LindanTian

This comment has been minimized.

Copy link

commented Oct 16, 2017

cool

@huzemin

This comment has been minimized.

Copy link

commented Oct 26, 2017

Thinks

@axd7832

This comment has been minimized.

Copy link

commented Nov 6, 2017

Simplicity is key. Thanks.

@n7best

This comment has been minimized.

Copy link

commented Nov 13, 2017

good stuff

@radius314

This comment has been minimized.

Copy link

commented Nov 15, 2017

👍

@Jeslopov

This comment has been minimized.

Copy link

commented Dec 14, 2017

Thanks

@FatemeNoruzi

This comment has been minimized.

Copy link

commented Dec 26, 2017

👍

@loyoliteabid

This comment has been minimized.

Copy link

commented Dec 29, 2017

Thanks

@geezywap

This comment has been minimized.

Copy link

commented Jan 12, 2018

@ManGysT

This comment has been minimized.

Copy link

commented Jan 23, 2018

Thnaks man!

@mhcreative

This comment has been minimized.

Copy link

commented Jan 25, 2018

Thanks. Great, simple script.

@shradha03

This comment has been minimized.

Copy link

commented Feb 8, 2018

Thanks, it was of great help.

@lcherone

This comment has been minimized.

Copy link

commented Feb 18, 2018

For any length IDs:

var ID = function (length) {
    if (!length) {
        length = 8
    }
    var str = ''
    for (var i = 1; i < length + 1; i = i + 8) {
        str += Math.random().toString(36).substr(2, 10)
    }
    return ('_' + str).substr(0, length)
}
@KalanaPerera

This comment has been minimized.

Copy link

commented Feb 22, 2018

Thanks!!

@lcherone

This comment has been minimized.

Copy link

commented Feb 26, 2018

Another way which uses a cryptographically secure random number generator, in UUID format.

var ID = () => {
  let array = new Uint32Array(8)
  window.crypto.getRandomValues(array)
  let str = ''
  for (let i = 0; i < array.length; i++) {
    str += (i < 2 || i > 5 ? '' : '-') + array[i].toString(16).slice(-4)
  }
  return str
}
@proishan11

This comment has been minimized.

Copy link

commented Mar 13, 2018

Great! Can we write a unit test for this function? I am unable to figure out how to approach this. Thanks 😄

@ghost

This comment has been minimized.

Copy link

commented Mar 30, 2018

Generating unique id's is a bigger headache than I thought. If there's anything to study its how to do this correctly because I've seen plenty of implementations that claim to work but are then quickly discredited.

@Planeur

This comment has been minimized.

Copy link

commented Apr 14, 2018

Math.random() is not unique. But time stamp generated ids could be.

@Planeur

This comment has been minimized.

Copy link

commented Apr 14, 2018

a simple way to do this:

(new Date().getTime()).toString(36)

@williamyeny

This comment has been minimized.

Copy link

commented Apr 28, 2018

@Planeur Timestamp IDs are technically not unique because you could have the same ID if the IDs are generated within the same millisecond. Try combining timestamp and Math.random to make it even more unlikely for collisions

var ID = Date.now() + Math.random().toString().slice(2);

@krisan012

This comment has been minimized.

Copy link

commented May 7, 2018

awesome thanks :D

@jorhel

This comment has been minimized.

Copy link

commented Jun 13, 2018

Thankyou from the help.
My code:

function genID(){
    this.inner = [];
    this.unique = function( id ){
        for( var actID in this.inner ){
           if( actID === this.inner ){
                break;
               return false;
           }
        }
        return id;
    };
    this.gen = function( len ){
        len = typeof len !== "number" ? 36 : len;
        let id = false;
        while( !id ){
            id = this.unique('_' + (Date.now().toString( len ) + Math.random().toString( len ).substr(2, 5)).toUpperCase());
        }
         this.inner.push( id );
        console.log( this.inner );
        return id;
    };
    return this;
}

Use:

var foo = new genID();
console.log( foo.gen() );
console.log( foo.gen() );

@yukulele

This comment has been minimized.

Copy link

commented Jul 18, 2018

Math.round((Math.random() * 36 ** 12)).toString(36);
// "u8dbda25zwik"
@Saifeddine-Rjab

This comment has been minimized.

Copy link

commented Sep 1, 2018

Thanks this is very helpful

@robsongajunior

This comment has been minimized.

Copy link

commented Sep 19, 2018

random and timestamp based at milions request maybe it is not unic...
.. should be implemented using RFC4122

Using JavaScript the correct way it is using UUID4, based in random.
uuid-v4.js

@Horse303

This comment has been minimized.

Copy link

commented Sep 20, 2018

Hello. Thank you for posting this.
I did some testing to see how often collisions will occur (because for my nodejs RPG game, low length id is required and well, have as less collisions as possible).
I was very surprised with results.
(HashMap is my container, written in typescript)

I am failing to force this stupid post GUI to style the code. Therefore: code starts here:

`
results:
//stats results:
//1000 ids generated: 0 collisions
//10000 ids generated: 0 collisions
//100000 ids generated: 0 collisions
//1 milion ids generated: 0 collisions
//10 milion ids generated: 0 collisions

it('Collision finding', (done) => {
var hm = new HashMap<string, number>();
var iterations = 10000000;
var collisionsFound = 0;
for (let i = 0; i < iterations; i++) {
var id = Math.random().toString(36).substr(2, 9);
while (hm.contains(id)) {
console.log('id ${id} collision');
id = Math.random().toString(36).substr(2, 9);
collisionsFound++;
}
hm.insert(id, 2);
}
console.log('had ${collisionsFound} collisions in ${iterations} iterations');
});`

@Tusbahle

This comment has been minimized.

Copy link

commented Oct 17, 2018

thanks !, it helped me....

@igorrybalko

This comment has been minimized.

Copy link

commented Oct 23, 2018

Thanks, great solution.

@lmj0011

This comment has been minimized.

Copy link

commented Nov 8, 2018

For anonymous analytic collecting from a pool of 10's of thousands of active users, maybe 100's, OP's solution should be fine to use.

However, I decided to tinker with my own implementation and came up with this (piggybacking off of @Planeur):

'_' + (new Date().getUTCMilliseconds().toString() + new Date().getTime().toString()).toString();

// "_4511541719590451"

not sure the base it would take to convert this into an alphanumerical string

@zhiwenjunjin

This comment has been minimized.

Copy link

commented Nov 12, 2018

when you pick the substring, how can you be sure it is still unique?

@neyron163

This comment has been minimized.

Copy link

commented Nov 21, 2018

Thanks

@jaitheking

This comment has been minimized.

Copy link

commented Dec 10, 2018

Thank you. This is simple and easy to use

@notikatoti

This comment has been minimized.

Copy link

commented Jan 19, 2019

Thank

@Waldemar999

This comment has been minimized.

Copy link

commented Feb 21, 2019

thanks

@tripflex

This comment has been minimized.

Copy link

commented Feb 26, 2019

var ID = () => {
let array = new Uint32Array(8)
window.crypto.getRandomValues(array)
let str = ''
for (let i = 0; i < array.length; i++) {
str += (i < 2 || i > 5 ? '' : '-') + array[i].toString(16).slice(-4)
}
return str
}

Works great thank you!

@yedincisenol

This comment has been minimized.

Copy link

commented Mar 11, 2019

Thank you :)

@awesomeandrey

This comment has been minimized.

Copy link

commented Apr 2, 2019

ty sir

@AlexisThink

This comment has been minimized.

Copy link

commented Apr 4, 2019

Great! Thank you

@maurisrx

This comment has been minimized.

Copy link

commented Apr 5, 2019

Thank you! Simple yet reliable.

@phaberest

This comment has been minimized.

Copy link

commented Apr 22, 2019

Amazing, I was having issues using Device.uuid as it somehow breaks the new privacy rules, thanks!

@satish4linux

This comment has been minimized.

Copy link

commented May 3, 2019

Thank you! worked great..!

@ronit-mukherjee

This comment has been minimized.

Copy link

commented Jun 5, 2019

Thanks :), It's helpful

@reheem

This comment has been minimized.

Copy link

commented Jun 7, 2019

function random_id() {
  return '_' + (
    Number(String(Math.random()).slice(2)) + 
    Date.now() + 
    Math.round(performance.now())
  ).toString(36);
}
@DMPR-dev

This comment has been minimized.

Copy link

commented Sep 12, 2019

thanks

@XemaA

This comment has been minimized.

Copy link

commented Oct 5, 2019

@marcosschlup How are you sure it'll be a random unique id?

@abdulhannanali Date.now() will garentee that is unique :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.