Pergunta

Eu estou tentando criar identificadores globalmente únicos em JavaScript. Eu não tenho certeza do que rotinas estão disponíveis em todos os navegadores, como "aleatório" e semeado o built-in gerador de números aleatórios é, etc ..

O GUID / UUID deve ser pelo menos 32 caracteres e deve ficar na faixa de ASCII para problemas evitar ao passá-los ao redor.

Foi útil?

Solução

UUID (universalmente identificador único), também conhecidos como Guids (identificador exclusivo), de acordo com RFC 4122 , são identificadores com uma certa garantia singularidade.

A melhor maneira de gerá-los, é seguir as instruções de implementação no referido RFC, use um dos muitos comunidade vetado implementações de código aberto.

ferramenta

Um populares Open Source para trabalhar com UUIDs em JavaScript é nó-uuid

Note que apenas gerar aleatoriamente o identificadores byte por byte, ou caractere por caractere, não lhe dará as mesmas garantias que a aplicação conformes. Além disso, muito importantes, sistemas que trabalham com UUIDs compatíveis podem optar por não aceitar os gerados aleatoriamente, e muitos validadores de código aberto vai realmente verificar se há uma estrutura válido.

Um UUID deve ter o seguinte formato:

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

Quando o M e N posições só pode ter certos valores. Neste momento, os valores válidos para M são 1, 2, 3, 4 e 5, de modo a gerar aleatoriamente nessa posição seria fazer a maioria dos resultados inaceitáveis.

Outras dicas

Para uma href="https://www.ietf.org/rfc/rfc4122.txt" rel="noreferrer"> RFC4122 solução compatível

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 : Esteja ciente de que UUID singularidade depende muito do gerador de números aleatórios subjacente (RNG). A solução acima usa Math.random() por brevidade, no entanto Math.random() é não garantido para ser um RNG de alta qualidade. Consulte excelente writeup de Adão Hyland em Math.random () para mais detalhes. Para uma solução mais robusta, considerar algo como o UUID módulo [Disclaimer: Eu sou o autor] , que usa APIs RNG maior qualidade quando disponível.

Update, 2015/08/26 : Como uma nota lateral, este essência descreve como determinar quantos IDs podem ser gerados antes de chegar a uma determinada probabilidade de colisão. Por exemplo, com 3.26x10 15 Versão 4 UUIDs RFC4122 você tem um 1-em-um-milhão de chance de colisão.

Update, 2017/06/28 : A bom artigo de desenvolvedores do Chrome discutir o estado da qualidade Math.random PRNG no Chrome, Firefox e Safari. tl; dr - A partir do final de 2015 de "muito bom", mas não a qualidade criptográfica. Para abordar essa questão, aqui está uma versão atualizada da solução acima que usa ES6, a API crypto e um pouco de JS wizardy Eu não posso levar o crédito 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());

resposta

O broofa é muito escorregadio, de fato - impressionantemente esperto, realmente ... rfc4122 compliant, pouco legível, e compacto. Awesome!

Mas se você está olhando para essa expressão regular, aqueles muitos callbacks replace(), chamadas de função de toString() e Math.random() (onde ele está apenas usando 4 bits do resultado e desperdiçando o resto), você pode começar a se perguntar sobre o desempenho. Na verdade, joelpt mesmo decidiu jogar fora RFC para a velocidade GUID genérico com generateQuickGUID.

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

Mas, primeiro, os meus resultados, em comparação com broofa, guid (a resposta aceita), eo generateQuickGuid-não-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.

Assim, a minha sexta iteração de otimizações, bati a resposta mais popular em mais de 12X, a resposta aceita por mais, ea resposta 9X fast-non-compliant por 2-3X . E eu ainda estou compatível rfc4122.

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

Para obter 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 que substitui x com qualquer dígito hexadecimal aleatório, y com dados aleatórios (exceto forçando o top 2 bits para 10 acordo com a especificação RFC), e o regex não coincide com os personagens - ou 4, então ele não faz tem que lidar com eles. Muito, muito liso.

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

O primeiro passo para o desempenho é eliminar a suas funções de retorno de chamada RegEx e usar um loop simples em seu lugar. Isso significa que temos de lidar com os personagens - e 4 enquanto broofa não. Além disso, nota que podemos usar cordas de indexação de matriz para manter a mancha de Cordas arquitetura template:

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, a não ser que verificar se há - ou 4, e usando um loop while (em vez de chamadas de retorno replace()) fica-nos um quase melhoria 3X!

O próximo passo é um pequeno no ambiente de trabalho, mas faz uma diferença decente no celular. Vamos fazer menos chamadas Math.random () e utilizar todos esses bits aleatórios em vez de jogar 87% deles afastado com um tampão aleatório que fica deslocado para fora cada iteração. Vamos também mover essa definição do modelo fora do circuito, apenas no caso de ajuda:

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 poupa de 10-30%, dependendo da plataforma. Não é ruim. Mas o próximo grande passo se livrar das chamadas de função toString em conjunto com uma otimização clássico - a tabela look-up. Uma simples tabela de referência de 16 elemento irá 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
}

O próximo otimização é outro clássico. Uma vez que estamos a manipulação única 4-bits de saída em cada iteração do loop, vamos cortar o número de loops ao meio e processo de 8-bits cada iteração. Isto é complicado, uma vez que ainda tem que lidar com as posições de bits compatíveis com RFC, mas não é muito difícil. Temos, então, fazer uma tabela de pesquisa maior (16x16, ou 256) para armazenar 0x00 -. 0xff, e nós construí-lo 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 uma e6 () que processa 16-bits de cada vez, ainda usando o 256-elemento LUT, e ele mostrou os retornos decrescentes de otimização. Embora tivesse menos iterações, a lógica interna foi complicada por taumentou o processamento, e realizado o mesmo no desktop, e apenas ~ 10% mais rápido no celular.

A técnica de otimização final a aplicar - desenrolar o loop. Desde que nós estamos looping um número fixo de vezes, podemos tecnicamente escrever isso tudo à mão. Tentei fazer isso uma vez com uma única variável aleatória r que eu mantive re-atribuição, e desempenho despencou. Mas, com quatro variáveis ??atribuídos dados aleatórios na frente, em seguida, usando a tabela de referência, e aplicando os bits RFC adequadas, esta versão fuma todos eles:

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

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

O engraçado é que, gerando 16 bytes de dados aleatórios é a parte fácil. Todo o truque é expressá-la no formato de cadeia com o cumprimento RFC, e é mais bem realizado com 16 bytes de dados aleatórios, um loop e consulta à tabela desenrolado.

Espero que a minha lógica é correta - é muito fácil cometer um erro neste tipo de bit-trabalho tedioso. Mas as saídas de olhar bem para mim. Espero que tenham gostado desta viagem louca através da otimização de código!

Esteja ciente: meu objetivo principal era mostrar e ensinar estratégias de otimização de potenciais. Outras respostas abrangem temas importantes, como colisões e números aleatórios, que são importantes para a geração de bons UUIDs.

Aqui está um código baseado em RFC 4122 , secção 4.4 (Algoritmos para criar um UUID a partir Verdadeiramente aleatórios ou números pseudo-aleatórios).

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;
}
var uniqueId = Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36);

Se o ID são gerados mais de 1 milissegundo separados, eles são 100% original.

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

Você pode aumentar este número, adicionando mais dígitos, mas para gerar 100% original ID é que você vai precisar usar um contador global.

Se você realmente precisa de conformidade RFC, esta formatação vai passar como um válido versão 4 GUID:

const uid = (new Date()).getTime().toString(16) + Math.random().toString(16).substring(2) + "0".repeat(16);
const guid = uid.substr(0,8) + '-' + uid.substr(8,4) + '-4000-8' + uid.substr(12,3) + '-' + uid.substr(15,12);

Edit: O código acima siga a intenção, mas não a letra da RFC. Entre outras discrepâncias que é um pouco aleatório dígitos curto. (Adicionar mais dígitos aleatórios, se você precisar dele) A vantagem é que este é muito rápido, em comparação com código compatível com 100%. Você pode testar sua GUID aqui

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

dez milhões de execuções de esta implementação demorar apenas 32.5 segundos, o que é o mais rápido que eu já vi em um navegador (a única solução sem Loops / iterações).

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

/**
 * Generates a GUID string.
 * @returns {String} The generated GUID.
 * @example af8a8416-6e18-a307-bd9c-f2c947bbb3aa
 * @author Slavik Meltser (slavik@meltser.info).
 * @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 esse código:

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

Eu tenho certeza que a maioria de vocês vai entender o que eu fiz lá, mas talvez haja pelo menos uma pessoa que precisa 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 decimal fracção (por exemplo 0.4363923368509859).
  • Em seguida, tomamos este número e convertido -lo para uma string com base 16 (a partir do exemplo acima nós vamos chegar 0.6fb7687f).
    Math.random().toString(16).
  • Em seguida, cortou o prefixo 0. (0.6fb7687f => 6fb7687f) e obter uma string com oito hexadecimal caracteres.
    (Math.random().toString(16).substr(2,8).
  • Às vezes a função Math.random() voltará menor número (por exemplo 0.4363), devido a zeros no final (a partir do exemplo acima, na verdade, o número é 0.4363000000000000). É por isso que eu estou anexando a este "000000000" string (uma string com nove zeros) e, em seguida, cortando-a com a função substr() para torná-lo nove caracteres exatamente (enchimento zeros à direita).
  • A razão para adicionar exatamente nove zeros é por causa do pior cenário, que é quando a função Math.random() irá retornar exatamente 0 ou 1 (probabilidade de 10/01 ^ 16 para cada um deles). É por isso que precisávamos para adicionar nove zeros a ele ("0"+"000000000" ou "1"+"000000000"), e depois cortando-à partir do segundo índice (3 caracteres) com um comprimento de oito caracteres. Para o resto dos casos, a adição de zeros não irá prejudicar o resultado porque ele está cortando-a de qualquer maneira.
    Math.random().toString(16)+"000000000").substr(2,8).

A montagem:

  • O GUID está no seguinte formato XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.
  • I dividiu o GUID em 4 pedaços, cada peça dividida em 2 tipos (ou formatos):. XXXXXXXX e -XXXX-XXXX
  • Agora eu estou construindo o GUID usando estes 2 tipos de montar o GUID com a chamada 4 peças, como segue:. XXXXXXXX -XXXX-XXXX -XXXX-XXXX XXXXXXXX
  • Para diferem entre estes dois tipos, eu adicionei um parâmetro de bandeira para uma função _p8(s) par criador, o parâmetro s conta a função se deseja adicionar traços ou não.
  • Eventualmente vamos construir o GUID com o seguinte encadeamento:. _p8() + _p8(true) + _p8(true) + _p8(), e devolvê-lo

Link para este post no meu blog

Divirta-se! : -)

Aqui é uma combinação de topo votou resposta , com uma solução alternativa para Chrome's colisões :

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

Em jsbin se você quiser testá-lo.

Aqui é uma implementação totalmente não-compatível, mas muito alto desempenho para gerar um ASCII-safe GUID-como identificador único.

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

Gera 26 caracteres [A-Z0-9], produzindo uma UID que é tanto mais curto e mais original do que GUIDs compatíveis com RFC. Os traços podem ser trivialmente adicionados se assuntos humanos legibilidade.

Aqui estão exemplos de uso e horários para esta função e várias outras respostas desta pergunta. O momento foi realizada sob 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 datado de 09 de outubro de 2011 a partir de um comentário 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)}

Esta realiza o mesmo objetivo que o corrente mais alta -rated resposta , mas em 50+ menos bytes por coerção exploração, recursão, e notação exponencial. Para os curiosos como ele funciona, aqui está o formulário anotada de uma versão mais 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
      )
}

A partir sagi de shkedy blog técnico :

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

Existem outros métodos que envolvem o uso de um controle ActiveX, mas ficar longe de estes!

Editar: Eu pensei que era importante ressaltar que nenhum gerador GUID pode garantir chaves únicas (verifique o wikipedia artigo ). Há sempre a chance de colisões. Um GUID é simples e oferece um universo grande o suficiente de chaves para reduzir a mudança de colisões a quase zero.

Você pode usar o nó-uuid ( https://github.com/kelektiv/node-uuid)

Simples, geração rápida de RFC4122 UUIDs.

características:

  • Gerar RFC4122 versão 1 ou versão 4 UUIDs
  • É executado em node.js e navegadores.
  • Cryptographically forte # geração aleatória no apoio a plataformas.
  • Pequenas dimensões (quer algo menor? Confira! )

Instalar Usando NPM:

npm install uuid

ou usar uuid via browser:

Baixar Raw Arquivo (v1 uuid): https: // cru. githubusercontent.com/kelektiv/node-uuid/master/v1.js Baixar Arquivo Raw (v4 uuid): https://raw.githubusercontent.com /kelektiv/node-uuid/master/v4.js


Quer ainda menor? Vejam isto: https://gist.github.com/jed/982883


Uso:

// 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 namespace
const MY_NAMESPACE = '(previously generated unique uuid string)';
uuidV5('hello', MY_NAMESPACE); // -> '90123e1c-7512-523e-bb28-76fab9f2f73d'

ES6:

import uuid from 'uuid/v4';
const id = uuid();

Um serviço web seria útil.

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

Não é possível garantir para essa implementação, mas alguém deve publicar um gerador genuíno GUID.

Com esse serviço a web, você poderia desenvolver uma interface web REST que consome o serviço Web GUID, e serve-lo através de AJAX para JavaScript em um navegador.

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

EDIT:

Revisited meu projeto que foi com essa função e não gostou do verbosidade. -. Mas precisava de aleatoriedade adequada

Uma versão com base na resposta do Briguy37 e alguns operadores bit a bit para extrair janelas de tamanho mordidela do buffer.

devem aderir ao esquema RFC Tipo 4 (aleatório), desde que eu tinha problemas de última hora analisar UUIDs não compatíveis com UUID de Java.

módulo de JavaScript simples como uma combinação de melhores respostas neste tópico.

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 boa ol' wikipedia há um link para uma implementação javascript de UUID.

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

UPDATE: O site original teve um shuffle, aqui é o versão atualizada

Bem, isso tem um monte de respostas já, mas infelizmente não há uma "verdadeira" aleatório no grupo. A versão abaixo é uma adaptação da resposta de broofa, mas atualizado para incluir uma "verdadeira" função aleatória que usa bibliotecas de criptografia onde está disponível e a função Alea () como um 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 http://baagoe.com/en/RandomMusings/javascript/
      // Johannes Baagøe <baagoe@baagoe.com>, 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 <baagoe@baagoe.com>, 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);
  });
};

Este criar versão 4 UUID (criado a partir de números aleatórios pseudo):

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

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

UUID.js O RFC-compliant gerador UUID para JavaScript.

Veja RFC 4122 http://www.ietf.org/rfc/rfc4122.txt .

Características Gera UUIDs compatíveis com RFC 4122.

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

objeto UUID permite uma variedade de acesso ao UUID incluindo o acesso a os campos UUID.

Baixa timestamp resolução de JavaScript é compensado por acaso números.

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

Ajustado meu próprio UUID / gerador GUID com alguns extras aqui .

Eu estou usando o seguinte Kybos gerador de números aleatórios a ser um pouco som mais cryptographically .

Abaixo está o 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 <baagoe@baagoe.com>, 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));

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}

Eu queria entender a resposta de broofa, então eu expandiu e acrescentou comentários:

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

Exemplo de ES6

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

É apenas uma chamada de AJAX simples ...

Se alguém ainda está interessado, aqui está a minha solução.

No lado do servidor:

[WebMethod()]
public static string GenerateGuid()
{
    return Guid.NewGuid().ToString();
}

No lado do cliente:

var myNewGuid = null;
PageMethods.GenerateGuid(
    function(result, userContext, methodName)
    {
        myNewGuid = result;
    },
    function()
    {
        alert("WebService call failed.");
    }
);

Para aqueles que querem uma versão rfc4122 solução compatível 4 com considerações de velocidade (algumas chamadas para Math.random ()):

function UUID() {
    var nbr, randStr = "";
    do {
        randStr += (nbr = Math.random()).toString(16).substr(2);
    } 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)
        ].join("");
}

A função acima deve ter um equilíbrio decente entre velocidade e aleatoriedade.

Este é baseado na data, e adicionar um sufixo aleatório a singularidade "garantir". Funciona bem para identificadores CSS. Ele sempre retorna algo parecido e é fácil de cortar:

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

Eu sei, é uma questão antiga. Apenas para completar, se o ambiente é SharePoint, há uma função de utilitário chamado SP.Guid.newGuid ( ligação MSDN) que cria um novo GUID. Esta função está dentro do arquivo sp.init.js. Se você reescrever essa função (para remover algumas outras dependências de outros eventos privados), parece que isso:

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

Existe um plugin jQuery que alças de Guid bem @ http://plugins.jquery.com/project/ GUID_Helper

jQuery.Guid.Value()

devolve o valor da Guid interno. Se nenhum guid foi especificado, retorna uma nova (valor é então armazenado internamente).


jQuery.Guid.New()

Retorna um novo Guid e conjuntos seu valor internamente.


jQuery.Guid.Empty()

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


jQuery.Guid.IsEmpty()

Retorna o booleano. Verdadeiro se vazia / indefinido / branco / null.


jQuery.Guid.IsValid()

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


jQuery.Guid.Set()

Retrns Guid. Sets GUID para usuário especificado Guid, se inválido, retorna um guid vazia.

código simples que usa crypto.getRandomValues(a) em navegadores suportados (IE11 +, iOS7 +, FF21 +, Chrome, Android ). Evita usar Math.random() porque isso pode causar colisões (por exemplo, 20 colisões para 4000 UUIDs gerados em uma situação real de Muxa ).

function uuid() {
    function randomDigit() {
        if (crypto && crypto.getRandomValues) {
            var rands = new Uint8Array(1);
            crypto.getRandomValues(rands);
            return (rands[0] % 16).toString(16);
        } else {
            return ((Math.random() * 16) | 0).toString(16);
        }
    }
    var crypto = window.crypto || window.msCrypto;
    return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/x/g, randomDigit);
}

Notas:

  • Optimizado para facilitar a leitura do código não velocidade, de modo adequado para dizer algumas centenas de UUID por segundo. Gera cerca de 10000 uuid () por segundo no Chromium no meu laptop usando http://jsbin.com/fuwigo/1 para medir o desempenho.
  • Apenas usa 8 para "y", porque que simplifica a legibilidade do código (y é permitido para ser de 8, 9, A ou B).
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top