javascript - number - uuid react js




Criar GUID/UUID em JavaScript? (20)

A resposta de Broofa é bem bacana, de fato - impressionantemente inteligente, realmente ... compatível com rfc4122, um tanto legível e compacta. Impressionante!

Mas se você está olhando para essa expressão regular, esses muitos replace() callbacks, chamadas de função toString() e Math.random() (onde ele está usando apenas 4 bits do resultado e desperdiçando o resto), você pode iniciar se perguntar sobre desempenho. De fato, o joelpt até decidiu lançar o RFC para a velocidade genérica do GUID com generateQuickGUID .

Mas podemos obter velocidade e conformidade com RFC? Eu digo sim! Podemos manter a legibilidade? Bem ... Na verdade não, mas é fácil se você seguir junto.

Mas primeiro, meus resultados, comparados a broofa, guid (a resposta aceita), e o generateQuickGuid compatível com rfc:

                  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   10762ms
generateQuickGuid:  292ms    2961ms
  - Note: 500k iterations, results will vary by browser/cpu.

Então, com minha 6ª iteração de otimizações, eu venci a resposta mais popular por mais de 12X , a resposta aceita por mais de 9X , e a resposta rápida não compatível por 2-3X . E ainda sou compatível com rfc4122.

Interessado em como? Eu coloquei a fonte completa em http://jsfiddle.net/jcward/7hyaC/3/ e em http://jsperf.com/uuid-generator-opt/4

Para uma explicação, vamos começar com o código do broofa:

'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);
});

Assim, ele substitui x por qualquer dígito hexagonal aleatório, y com dados aleatórios (exceto forçar os 2 bits superiores a 10 pela especificação RFC), e o regex não corresponde aos - ou 4 caracteres, então ele não precisa lidar com eles. Muito, muito liso.

A primeira coisa a saber é que as chamadas de função são caras, assim como expressões regulares (embora ele use apenas 1, tem 32 retornos de chamada, um para cada correspondência e em cada um dos 32 retornos de chamada que chama Math.random () e v. toString (16)).

O primeiro passo para o desempenho é eliminar o RegEx e suas funções de retorno de chamada e usar um loop simples. Isso significa que temos que lidar com os - e 4 caracteres enquanto broofa não. Além disso, observe que podemos usar a indexação de String Array para manter sua arquitetura de gabarito String:

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;
}

Basicamente, a mesma lógica interna, exceto que nós verificamos - ou 4 , e usando um loop while (ao invés de callbacks replace() ) nos obtém uma melhoria de quase 3 vezes!

O próximo passo é pequeno na área de trabalho, mas faz uma diferença decente no celular. Vamos fazer menos chamadas Math.random () e utilizar todos esses bits aleatórios ao invés de jogar 87% deles com um buffer aleatório que é deslocado para fora de cada iteração. Vamos também mover essa definição de modelo para fora do loop, caso isso ajude:

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
}

Isso nos economiza 10-30% dependendo da plataforma. Não é ruim. Mas o próximo grande passo se livra das chamadas de função toString juntamente com um clássico de otimização - a tabela de consulta. Uma simples tabela de pesquisa de 16 elementos executará o trabalho de toString (16) em muito menos tempo:

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
}

A próxima otimização é outro clássico. Como estamos lidando com apenas 4 bits de saída em cada iteração de loop, vamos cortar o número de loops ao meio e processar 8 bits cada iteração. Isso é complicado, pois ainda temos que lidar com as posições de bits compatíveis com RFC, mas não é muito difícil. Em seguida, temos que fazer uma tabela de pesquisa maior (16x16 ou 256) para armazenar 0x00 - 0xff e a construímos apenas uma vez, fora da função e5 ().

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
}

Eu tentei um e6 () que processa 16 bits de cada vez, ainda usando o LUT de 256 elementos, e mostrou os retornos decrescentes de otimização. Embora tivesse menos iterações, a lógica interna era complicada pelo aumento do processamento, e o desempenho era o mesmo na área de trabalho, e apenas 10% mais rápido no celular.

A técnica de otimização final a ser aplicada - desenrole o loop. Como estamos em loop por um número fixo de vezes, podemos tecnicamente escrever tudo isso a mão. Eu tentei isso uma vez com uma única variável aleatória r que eu continuei reatribuindo e desempenho tanked. Mas com quatro variáveis ​​atribuídas dados aleatórios na frente, usando a tabela de consulta e aplicando os bits RFC apropriados, esta versão os fuma:

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];
}

Modualizado: http://jcward.com/UUID.js - UUID.generate()

O engraçado é que gerar 16 bytes de dados aleatórios é a parte fácil. O truque todo é expressá-lo em formato String com conformidade com RFC, e é mais bem realizado com 16 bytes de dados aleatórios, um loop desenrolado e uma tabela de consulta.

Espero que minha lógica esteja correta - é muito fácil cometer um erro nesse tipo de trabalho tedioso. Mas as saídas parecem boas para mim. Espero que tenham gostado desse passeio louco por meio da otimização de código!

Esteja avisado: meu principal objetivo era mostrar e ensinar possíveis estratégias de otimização. Outras respostas abrangem tópicos importantes, como colisões e números verdadeiramente aleatórios, que são importantes para gerar bons UUIDs.

Estou tentando criar identificadores globais exclusivos em JavaScript. Não tenho certeza de quais rotinas estão disponíveis em todos os navegadores, como "aleatório" e semeado o gerador de números aleatórios integrado, etc.

O GUID / UUID deve ter pelo menos 32 caracteres e deve permanecer na faixa ASCII para evitar problemas ao transmiti-los.


Aqui está um código baseado no ietf.org/rfc/rfc4122.txt , seção 4.4 (Algoritmos para Criar um UUID de Verdadeiramente Aleatório ou Número Pseudo-Random).

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;
}

Aqui está uma implementação totalmente incompatível, mas de alto desempenho, para gerar um identificador exclusivo semelhante a GUID, seguro para ASCII.

function generateQuickGuid() {
    return Math.random().toString(36).substring(2, 15) +
        Math.random().toString(36).substring(2, 15);
}

Gera 26 [a-z0-9] caracteres, gerando um UID menor e mais exclusivo que os GUIDs compatíveis com RFC. Traços podem ser adicionados trivialmente se a legibilidade humana for importante.

Aqui estão exemplos de uso e horários para esta função e várias outras respostas desta pergunta. O timing foi realizado sob o Chrome m25, 10 milhões de iterações cada.

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

Aqui está o código de tempo.

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

Aqui está uma solução datada de 9 de outubro de 2011 de um comentário feito pelo usuário jed em https://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)}

Isso alcança o mesmo objetivo que a resposta mais bem avaliada atual , mas com menos de 50 bytes explorando a notação de coerção, recursão e exponencial. Para aqueles curiosos como funciona, aqui está a forma anotada de uma versão antiga da função:

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
      )
}

Eu realmente gosto de quão limpa a resposta de Broofa é, mas é lamentável que implementações pobres de Math.random deixem a chance de colisão.

Aqui está uma ietf.org/rfc/rfc4122.txt semelhante ietf.org/rfc/rfc4122.txt versão 4 da ietf.org/rfc/rfc4122.txt , que resolve esse problema, compensando os primeiros 13 números hexadecimais por uma porção hexadecimal do timestamp. Dessa forma, mesmo que o Math.random esteja na mesma semente, ambos os clientes teriam que gerar o UUID exatamente no mesmo milissegundo (ou mais de 10.000 anos depois) para obter o mesmo UUID:

function generateUUID() { // Public Domain/MIT
    var d = new Date().getTime();
    if (typeof performance !== 'undefined' && typeof performance.now === 'function'){
        d += performance.now(); //use high-precision timer if available
    }
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = (d + Math.random() * 16) % 16 | 0;
        d = Math.floor(d / 16);
        return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
    });
}


Aqui está um violino para testar.


GUID mais rápido como o método gerador de string no formato XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX . Isso não gera GUID compatível com padrão.

Dez milhões de execuções dessa implementação levam apenas 32,5 segundos, o que é o mais rápido que já vi em um navegador (a única solução sem loops / iterações).

A função é tão simples quanto:

/**
 * Generates a GUID string.
 * @returns {String} The generated GUID.
 * @example af8a8416-6e18-a307-bd9c-f2c947bbb3aa
 * @author Slavik Meltser ([email protected]).
 * @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();
}

Para testar o desempenho, você pode executar este código:

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

Tenho certeza que a maioria de vocês vai entender o que eu fiz lá, mas talvez haja pelo menos uma pessoa que precise de uma explicação:

O algoritmo:

  • A função Math.random() retorna um número decimal entre 0 e 1 com 16 dígitos após o ponto de fração decimal (por exemplo, 0.4363923368509859 ).
  • Então pegamos esse número e o convertemos em uma string com base 16 (do exemplo acima, obteremos 0.6fb7687f ).
    Math.random().toString(16) .
  • Em seguida, cortamos o prefixo 0. ( 0.6fb7687f => 6fb7687f ) e obtemos uma cadeia com oito caracteres hexadecimais de comprimento.
    (Math.random().toString(16).substr(2,8) .
  • Às vezes, a função Math.random() retornará um número menor (por exemplo, 0.4363 ), devido a zeros no final (a partir do exemplo acima, na verdade, o número é 0.4363000000000000 ). É por isso que estou anexando a esta string "000000000" (uma string com nove zeros) e depois cortando-a com a função substr() para criar exatamente nove caracteres (preenchendo zeros à direita).
  • O motivo para adicionar exatamente nove zeros é devido ao pior cenário, que é quando a função Math.random() retornará exatamente 0 ou 1 (probabilidade de 1/10 ^ 16 para cada um deles). É por isso que precisamos adicionar nove zeros a ele ( "0"+"000000000" ou "1"+"000000000" ) e, em seguida, cortá-lo do segundo índice (terceiro caractere) com um comprimento de oito caracteres. Para o resto dos casos, a adição de zeros não prejudicará o resultado porque está sendo cortada de qualquer maneira.
    Math.random().toString(16)+"000000000").substr(2,8) .

A montagem:

  • O GUID está no seguinte formato XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX .
  • Eu dividi o GUID em 4 partes, cada peça dividida em 2 tipos (ou formatos): XXXXXXXX e -XXXX-XXXX .
  • Agora estou construindo o GUID usando esses 2 tipos para montar o GUID com a chamada 4 partes, da seguinte maneira: XXXXXXXX -XXXX-XXXX -XXXX-XXXX XXXXXXXX .
  • Para diferir entre esses dois tipos, adicionei um parâmetro de sinalizador a uma função de par de criadores _p8(s) , o parâmetro s informa a função se deseja adicionar traços ou não.
  • Eventualmente, criamos o GUID com o seguinte encadeamento: _p8() + _p8(true) + _p8(true) + _p8() e retorná-lo.

Link para esta postagem no meu blog

Apreciar! :-)


Para uma solução compatível com a versão 4 da RFC4122 , esta solução de uma linha (ish) é a mais compacta que consegui criar:

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())

Atualização, 2015-06-02 : Esteja ciente de que a exclusividade do UUID depende muito do gerador de números aleatórios subjacente (RNG). A solução acima usa Math.random() para fins de brevidade, no entanto Math.random() não é garantia de ser um RNG de alta qualidade. Veja o excelente writeup de Adam Hyland em Math.random () para detalhes. Para uma solução mais robusta, considere algo como o módulo uuid [Disclaimer: I'm the author], que usa APIs RNG de maior qualidade quando disponíveis.

Atualização, 2015-08-26 : Como uma nota lateral, esta gist descreve como determinar quantos IDs podem ser gerados antes de atingir uma certa probabilidade de colisão. Por exemplo, com UUIDs RFC4122 de 3.26x10 15 versão 4, você tem uma chance de 1 em um milhão de colisão.

Atualização, 2017-06-28 : Um bom artigo de desenvolvedores do Chrome discutindo o estado da qualidade PRNG de Math.random no Chrome, Firefox e Safari. tl; dr - No final de 2015, é "muito bom", mas não tem qualidade criptográfica. Para resolver esse problema, aqui está uma versão atualizada da solução acima que usa o ES6, a API de crypto e um pouco de JS wizardy que eu não posso levar por :

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());


Um serviço da web seria útil.

Google rápido encontrado: http://www.hoskinson.net/GuidGenerator/

Não é possível garantir essa implementação, mas ALGUÉM deve publicar um gerador GUID genuíno.

Com esse serviço da Web, você pode desenvolver uma interface da Web REST que consuma o serviço da Web GUID e o veicule por meio do AJAX para o JavaScript em um navegador.


A melhor maneira:

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
              ?      // genetate 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
 }

Minimizado:

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}

Amostra ES6

const guid=()=> {
  const s4=()=> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);     
  return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4() + s4() + s4()}`;
}

Isto cria a versão 4 UUID (criada a partir de números pseudo-aleatórios):

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('');
}

Aqui está uma amostra dos UUIDs gerados:

682db637-0f31-4847-9cdf-25ba9613a75c
97d19478-3ab2-4aa1-b8cc-a1c3540f54aa
2eed04c9-2692-456d-a0fd-51012f947136

Módulo JavaScript simples como uma combinação das melhores respostas neste segmento.

var crypto = window.crypto || window.msCrypto || null; // IE11 fix

var 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);
    window.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 GUID
console.log(Guid.newGuid());

Uso:

Guid.newGuid ()

"c6c2d12f-d76b-5739-e551-07e6de5b0807"

Guid.empty

"00000000-0000-0000-0000-000000000000"


A partir da boa e velha Wikipédia, há um link para uma implementação de javascript do UUID.

Parece bastante elegante, e talvez pudesse ser melhorado salgando com um hash do endereço IP do cliente. Esse hash talvez possa ser inserido no lado do servidor de documento html para uso pelo javascript do lado do cliente.

ATUALIZAÇÃO: O site original teve um shuffle, aqui está a versão atualizada


Ajustou meu próprio gerador de UUID / GUID com alguns extras here .

Estou usando o seguinte gerador de números aleatórios Kybos para ser um pouco mais criptografado.

Abaixo está meu script com os métodos Mash e Kybos de baagoe.com excluídos.

//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));

Este é baseado na data e adiciona um sufixo aleatório para "garantir" a exclusividade. Funciona bem para identificadores de CSS. Ele sempre retorna algo assim e é fácil de hackear:

uid-139410573297741

var getUniqueId = function (prefix) {
            var d = new Date().getTime();
            d += (parseInt(Math.random() * 100)).toString();
            if (undefined === prefix) {
                prefix = 'uid-';
            }
            d = prefix + d;
            return d;
        };

Estranho que ninguém tenha mencionado isso ainda, mas para ser completo, há uma infinidade de geradores sobre npm . Estou disposto a apostar que a maioria deles também funciona no navegador.


Existe um plugin jQuery que lida com o Guid's agradavelmente @ http://plugins.jquery.com/project/GUID_Helper

jQuery.Guid.Value()

Retorna o valor do Guid interno. Se nenhum guia foi especificado, retorna um novo (o valor é então armazenado internamente).

jQuery.Guid.New()

Retorna um novo Guid e define seu valor internamente.

jQuery.Guid.Empty()

Retorna um Guid vazio 00000000-0000-0000-0000-000000000000.

jQuery.Guid.IsEmpty()

Retorna booleano. Verdadeiro se vazio / indefinido / branco / nulo.

jQuery.Guid.IsValid()

Retorna booleano. True válido guid, false se não.

jQuery.Guid.Set()

Retris Guid. Define o Guid para o Guid especificado pelo usuário, se inválido, retorna um guid vazio.


Projeto JavaScript no GitHub - https://github.com/LiosK/UUID.js

UUID.js O gerador UUID compatível com RFC para JavaScript.

Veja o RFC 4122 ietf.org/rfc/rfc4122.txt .

Recursos Gera UUIDs compatíveis com RFC 4122.

UUIDs da versão 4 (UUIDs de números aleatórios) e UUIDs da versão 1 (UUIDs baseados em tempo) estão disponíveis.

O objeto UUID permite uma variedade de acessos ao UUID, incluindo acesso aos campos UUID.

A baixa resolução de timestamp do JavaScript é compensada por números aleatórios.


  // 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('-');

var uniqueId = Math.random().toString(36).substring(2) 
               + (new Date()).getTime().toString(36);

Se os IDs forem gerados com mais de 1 milissegundo, eles são 100% exclusivos.

Se dois ID's são gerados em intervalos mais curtos, e assumindo que o método aleatório é verdadeiramente aleatório, isso geraria IDs com 99,9999999999999% de probabilidade de serem globalmente únicos (colisão em 1 de 10 ^ 15)

Você pode aumentar esse número adicionando mais dígitos, mas para gerar 100% de IDs exclusivos, você precisará usar um contador global.

document.getElementById("unique").innerHTML =
  Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36);
<div id="unique">
</div>





uuid