Créer GUID / UUID en JavaScript?

j'essaie de créer des identificateurs uniques à L'échelle mondiale en JavaScript. Je ne suis pas sûr de ce que les routines sont disponibles sur tous les navigateurs, comment "aléatoire" et semé le générateur de nombres aléatoires intégré est, etc..

le GUID / UUID doit être d'au moins 32 caractères et doit rester dans la gamme ASCII pour éviter les problèmes lors de leur passage.

3323
demandé sur Jason Cohen 2008-09-20 00:01:00

30 réponses

Il y a eu deux tentatives. La question Est: voulez-vous des GUIDs réels, ou juste des nombres aléatoires que look comme GUIDs? Il est assez facile de générer des nombres aléatoires.

function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}

cependant, notez que ces valeurs ne sont pas de véritables GUIDs .

Note : l'extrait de code fourni ne suit pas RFC4122 qui exige que la version ( 4 ) doit être intégré dans la sortie générée chaîne. N'utilisez pas cette réponse si vous avez besoin de gids conformes.

Utiliser:

var uuid = guid();

Démo:

function guid() {
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
}

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

document.getElementById('jsGenId').addEventListener('click', function() {
  document.getElementById('jsIdResult').value = guid();
})
input { font-family: monospace; }
<button id="jsGenId" type="button">Generate GUID</button>
<br>
<input id="jsIdResult" type="text" placeholder="Results will be placed here..." readonly size="40"/>
1975
répondu Jon Surrell 2018-08-31 19:51:17

pour une solution compatible RFC4122 version 4, Cette solution monocouche (ish) est la plus compacte que j'ai pu trouver.:

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

mise à jour, 2015-06-02 : soyez conscient que L'unicité UUID repose fortement sur le générateur de nombres aléatoires (RNG) sous-jacent. La solution ci-dessus utilise Math.random() pour la brièveté, cependant Math.random() est pas garanti d'être un RNG de haute qualité. Voir d'Adam Hyland, excellent writeup on Math.random () pour plus de détails. Pour une solution plus robuste, considérez quelque chose comme le module uuid [Disclaimer: je suis l'auteur], qui utilise des APIs RNG de meilleure qualité lorsqu'ils sont disponibles.

mise à jour, 2015-08-26 : comme une side-note, ce gist décrit comment déterminer combien D'Id peuvent être générés avant d'atteindre un une certaine probabilité de collision. Par exemple, avec 3.26x10 15 version 4 RFC4122 Uuid vous avez un 1-dans-un-million de chance de collision.

mise à Jour, 2017-06-28 : Un bon article à partir de Chrome développeurs discuter de l'état de Mathématiques.qualité PRNG aléatoire en Chrome, Firefox et Safari. tl; dr-à partir de fin 2015, c'est" assez bon", mais pas de qualité cryptographique. Pour aborder ce sujet, voici un version mise à jour de la solution ci-dessus qui utilise ES6, L'API crypto , et un peu de JS wizardy Je ne peux pas prendre le crédit pour :

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());
3238
répondu broofa 2018-05-25 16:34:28

j'aime vraiment comment nettoyer Broofa la réponse de , mais il est malheureux que les pauvres implémentations de Math.random laisser la chance de collision.

Voici une solution similaire RFC4122 version 4 qui résout ce problème en compensant les 13 premiers numéros hexadécimaux par une portion hexadécimale de l'horodatage. De cette façon, même si Math.random est sur la même graine, les deux clients devraient générer L'UUID à l'exacte même milliseconde (ou plus de 10.000 ans plus tard) pour obtenir le même 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);
    });
}



voici un violon à tester.

686
répondu Briguy37 2018-04-02 18:34:30

la réponse de broofa est assez habile, en effet-impressionnant intelligent, vraiment... conforme à la rfc4122, plutôt lisible, et compact. Génial!

mais si vous regardez cette expression régulière, ces nombreux appels de fonction replace() , toString() et Math.random() (où il n'utilise que 4 bits du résultat et gaspille le reste), vous pouvez commencer à vous interroger sur la performance. En effet, joelpt a même décidé de jeter RFC pour générique GUID speed avec generateQuickGUID .

mais, pouvons-nous obtenir la vitesse et conformité RFC? Je dis, OUI! Pouvons-nous maintenir la lisibilité? Bien... Pas vraiment, mais c'est facile si vous suivez.

mais d'abord, mes résultats, comparés à broofa, guid (la réponse acceptée), et le non-conforme rfc generateQuickGuid :

                  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.

donc par ma 6ème itération d'optimisations, j'ai battu le plus réponse populaire par Plus de 12X , la réponse acceptée par Plus de 9X , et la réponse rapide-non conforme par 2-3X . Et je suis toujours compatible rfc4122.

comment? J'ai mis la source complète sur http://jsfiddle.net/jcward/7hyaC/3 / et sur http://jsperf.com/uuid-generator-opt/4

pour une explication, commençons avec le code de 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);
});

remplace x par n'importe quel HEX aléatoire, y par des données aléatoires (sauf forcer les 2 premiers bits à 10 selon la spécification RFC), et le regex ne correspond pas aux caractères - ou 4 , donc il n'a pas à traiter avec eux. Très, très lisse.

la première chose à savoir est que les appels de fonction sont coûteux, comme le sont les expressions régulières (bien qu'il utilise seulement 1, il dispose de 32 rappels, un pour chaque match, et dans chacun des 32 rappels il appelle les Mathématiques.random () et v. toString (16)).

la première étape vers la performance est d'éliminer le RegEx et ses fonctions de rappel et d'utiliser une boucle simple à la place. Cela signifie que nous devons traiter avec les caractères - et 4 alors que broofa ne l'a pas fait. Aussi, notez que nous pouvons utiliser l'indexation de Tableau de chaîne de caractères pour garder son architecture de modèle de chaîne de caractères:

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

fondamentalement, la même logique interne, sauf que nous vérifions pour - ou 4 , et en utilisant une boucle de temps (au lieu de replace() callbacks) nous obtient une amélioration presque 3X!

La prochaine étape est un petit sur le bureau, mais fait un décent différence sur mobile. Faisons de moins en Mathématiques.random () appelle et utilise tous ces bits aléatoires au lieu de jeter 87% d'entre eux avec un tampon aléatoire qui se déplace à chaque itération. Nous allons aussi se déplacer que définition du modèle de la boucle, juste au cas où cela aide:

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
}

cela nous économise 10-30% en fonction de la plate-forme. C'est pas mal. Mais la prochaine grande étape se débarrasse des appels de fonction toString tout à fait avec un classique de l'optimisation - la table de recherche. Une simple table de recherche à 16 éléments effectuera le travail de toString(16) en beaucoup moins de temps:

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
}

La prochaine optimisation est un autre classique. Puisque nous ne manipulons que 4-bits de sortie dans chaque itération de boucle, coupons le nombre de boucles en deux et traitons 8 bits chaque itération. C'est délicat car nous devons encore gérer les positions de bits conformes à la RFC, mais ce n'est pas trop difficile. Nous devons alors faire une plus grande table de recherche (16x16, ou 256) pour stocker 0x00 - 0xff, et nous ne la construisons qu'une seule fois, en dehors de la fonction 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
}

j'ai essayé un e6 () qui traite 16 bits à la fois, toujours en utilisant le LUT 256 éléments, et il a montré la diminution les retours de l'optimisation. Bien qu'il ait eu moins d'itérations, la logique interne a été compliquée par l'augmentation du traitement, et il a effectué la même chose sur le bureau, et seulement ~10% plus rapide sur mobile.

la dernière technique d'optimisation à appliquer-déroulez la boucle. Puisque nous sommes en boucle un nombre fixe de fois, nous pouvons techniquement écrire tout cela à la main. J'ai essayé une fois avec une seule variable aléatoire r que je n'arrêtais pas de réaffecter, et la performance a échoué. Mais avec quatre variables attribué données aléatoires à l'avant, puis à l'aide de la table de recherche, et d'appliquer le bon RFC bits, cette version fume tous:

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

réduit: http://jcward.com/UUID.js - UUID.generate()

La chose drôle est, générant 16 octets de données aléatoires est la partie facile. Le truc est de l'exprimer en format chaîne avec la conformité RFC, et c'est le plus étroitement accompli avec 16 octets de données aléatoires, un boucle déroulée et table de recherche.

j'espère que ma logique est correcte -- il est très facile de faire une erreur dans ce genre de travail fastidieux. Mais les sorties de regarder bon pour moi. J'espère que vous avez apprécié cette course folle à travers l'optimisation du code!

soyez avisé: mon objectif principal était de montrer et d'enseigner des stratégies d'optimisation potentielles. D'autres réponses couvrent des sujets importants tels que les collisions et les nombres vraiment aléatoires, qui sont importants pour générer de bons UUIDs.

326
répondu Jeff Ward 2018-08-03 19:45:08

voici un code basé sur RFC 4122 , section 4.4 (algorithmes pour créer un UUID à partir D'un nombre vraiment aléatoire ou Pseudo-aléatoire).

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;
}
140
répondu Kevin Hakanson 2011-10-25 22:37:37

méthode de générateur de chaîne de caractères la plus rapide au format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX . Cela ne génère pas de GUID conforme à la norme.

dix millions d'exécutions de cette implémentation prennent seulement 32,5 secondes, ce qui est la plus rapide que j'ai jamais vu dans un navigateur (la seule solution sans boucles/itérations).

la fonction est aussi simple que:

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

pour tester la performance, vous pouvez exécuter ce code:

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

je suis sûr que la plupart d'entre vous comprendront ce que j'ai fait là-bas, mais peut-être qu'il y a au moins une personne qui aura besoin d'une explication:

l'algorithme:

  • la fonction Math.random() renvoie un nombre décimal entre 0 et 1 avec 16 chiffres après le point de fraction décimale (pour exemple 0.4363923368509859 ).
  • alors nous prenons ce nombre et convertissons une chaîne avec base 16 (à partir de l'exemple ci-dessus, nous obtiendrons 0.6fb7687f ).

    Math.random().toString(16) .
  • puis on coupe le préfixe 0. ( 0.6fb7687f => 6fb7687f ) et obtenir une chaîne de huit hexadécimaux les caractères de long.

    (Math.random().toString(16).substr(2,8) .
  • parfois la fonction Math.random() reviendra nombre plus court (par exemple 0.4363 ), en raison de zéros à la fin (à partir de l'exemple ci-dessus, en fait le nombre est 0.4363000000000000 ). C'est pourquoi j'ajoute à cette chaîne "000000000" (une chaîne avec neuf zéros) et je la coupe ensuite avec la fonction substr() pour faire neuf caractères exactement (remplir des zéros à droite).
  • la raison pour ajouter exactement neuf zéros est en raison du pire scénario, qui est quand la fonction Math.random() retournera exactement 0 ou 1 (Probabilité de 1/10^16 pour chacun d'eux). C'est pourquoi nous avons dû y ajouter neuf zéros ( "0"+"000000000" ou "1"+"000000000" ), puis la couper du second index (3ème caractère) avec une longueur de huit caractères. Pour le reste des cas, l'ajout de zéros ne nuira pas au résultat car il le coupe de toute façon.

    Math.random().toString(16)+"000000000").substr(2,8) .

l'Assemblée:

  • le guide est dans le format suivant XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX .
  • j'ai divisé le guide en 4 pièces, chaque pièce divisée en 2 types (ou formats): XXXXXXXX et -XXXX-XXXX .
  • maintenant je construis le GUID en utilisant ces 2 types pour assembler le GUID avec appel 4 pièces, comme suit: XXXXXXXX -XXXX-XXXX -XXXX-XXXX XXXXXXXX .
  • pour différer entre ces deux types, j'ai ajouté un paramètre flag à une fonction de créateur de paires _p8(s) , le paramètre s indique à la fonction s'il faut ajouter des tirets ou non.
  • finalement nous construisons le GUID avec le chaînage suivant: _p8() + _p8(true) + _p8(true) + _p8() , et le retourner.

lien vers cet article sur mon blog

Profitez-en! :- )

79
répondu Slavik Meltser 2018-07-15 19:10:23
var uniqueId = Math.random().toString(36).substring(2) 
               + (new Date()).getTime().toString(36);

si les ID sont générés à plus d'une milliseconde d'intervalle, ils sont 100% uniques.

si deux ID sont générés à des intervalles plus courts, et en supposant que la méthode aléatoire est vraiment aléatoire, cela générerait des ID qui sont 99.99999999999999% susceptibles d'être globalement unique (collision dans 1 de 10^15)

vous pouvez augmenter ce nombre en ajoutant plus de chiffres, mais pour générer des ID 100% uniques, vous aurez besoin d'utiliser un compteur global.

document.getElementById("unique").innerHTML =
  Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36);
<div id="unique">
</div>
72
répondu Simon Rigét 2018-03-01 12:41:10

Voici une combinaison de la top réponse voté , avec une solution de contournement pour collisions de Chrome :

    generateGUID = (typeof(window.crypto)!= 'undefined' && 
                typeof(fenêtre.cryptographique.getRandomValues)!= 'undefined')?
    fonction() {
        // Si nous avons un PRNG cryptographiquement sécurisé, utilisez ce
        // /q/collisions lors de la génératrice-uuid-en-javascript-57937/"0"+ret;
            }
            retour ret;
        };
        de retour (S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));
    }

    :

    fonction() {
        // Sinon, utilisez les maths.aléatoire
        // /q/créer-guid-uuid-en-javascript-66424/"http://jsbin.com/uqives/3" rel="noreferrer">Sur jsbin    si vous voulez le tester.  

58
répondu ripper234 2017-05-23 11:47:36

Voici une solution datée D'octobre. 9, 2011 d'un commentaire de l'utilisateur jed à 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)}

cela permet d'atteindre le même objectif que la réponse actuellement la mieux cotée , mais en plus de 50 octets en exploitant la coercition, la récursion et la notation exponentielle. Pour ceux curieux comment cela fonctionne, voici la forme annotée d'une version plus ancienne de la fonction:

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
      )
}
54
répondu Jed Schmidt 2017-05-23 10:31:37

Voici une implémentation totalement non-conforme mais très performante pour générer un identifiant unique de type ASCII-safe GUID.

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

génère 26 caractères [a-z0-9], donnant un UID qui est à la fois plus court et plus unique que les Gids conformes à la RFC. Tirets peuvent être trivialement ajouté si la lisibilité des questions.

Voici des exemples d'utilisation et des timings pour cette fonction et plusieurs des autres réponses de cette question. Le timing était réalisé sous Chrome M25, 10 millions d'itérations chacun.

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

voici le code de synchronisation.

var r;
console.time('t'); 
for (var i = 0; i < 10000000; i++) { 
    r = FuncToTest(); 
};
console.timeEnd('t');
53
répondu joelpt 2013-01-21 21:52:57

à Partir de sagi shkedy technique du blog :

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

il y a d'autres méthodes qui impliquent l'utilisation D'un contrôle ActiveX, mais restez loin de celles-ci!

EDIT: j'ai pensé qu'il valait la peine de souligner qu'aucun générateur de GUID ne peut garantir des Clés uniques (voir l'article wikipedia ). Il y a toujours un risque de collision. Un guide offre simplement un univers assez grand de clés pour réduire le changement de collisions à presque zéro.

31
répondu Prestaul 2016-03-28 21:55:30

un service web serait utile.

Quick Google a trouvé: http://www.hoskinson.net/GuidGenerator /

ne peut pas se porter garant pour cette implémentation, mais QUELQU'un doit publier un générateur de GUID bonafide.

avec un tel service web, vous pourriez développer une interface Web de repos qui consomme le service Web de guide, et le Sert par AJAX à javascript dans un navigateur.

29
répondu Sean 2008-09-19 20:35:27
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:

revisita mon projet qui utilisait cette fonction et n'aimait pas la verbosité. - Mais il avait besoin d'un vrai hasard.

une version basée sur la réponse de Briguy37 et quelques opérateurs bitwise pour extraire les fenêtres de taille nibble du buffer.

devrait adhérer au schéma RFC de Type 4 (aléatoire), car j'ai eu des problèmes lors de la dernière analyse des uuids non conformes avec L'UUID de Java.

29
répondu sleeplessnerd 2015-09-11 22:32:03

module JavaScript Simple comme une combinaison des meilleures réponses dans ce fil.

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

Utilisation:

Guid.newGuid ()

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

Guid.vide

" 00000000-0000-0000-0000-000000000000"

28
répondu kayz1 2017-06-29 13:29:06

vous pouvez utiliser node-uuid ( https://github.com/kelektiv/node-uuid )

simple, génération rapide de RFC4122 UUIDS.

Dispose:

  • générer RFC4122 version 1 ou version 4 UUIDs
  • fonctionne en noeud.js et les navigateurs.
  • fort niveau de Chiffrement aléatoire # génération sur le soutien des plates-formes.
  • petite empreinte (vous voulez quelque chose de plus petit? regardez ça! )

installer en utilisant NPM:

npm install uuid

ou en utilisant uuid via le navigateur:

télécharger le fichier Raw (uuid v1): https://raw.githubusercontent.com/kelektiv/node-uuid/master/v1.js Télécharger Fichier brut (uuid v4): https://raw.githubusercontent.com/kelektiv/node-uuid/master/v4.js


vous voulez encore plus petit? Regardez ça: https://gist.github.com/jed/982883


Utilisation:

// 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();
26
répondu Kyros Koh 2018-09-21 04:58:54

From good ol 'wikipedia il y a un lien vers une implémentation javascript de UUID.

il semble assez élégant, et pourrait peut-être être être améliorée en salant avec un hachage de l'adresse IP du client. Ce hachage pourrait peut-être être inséré du côté du serveur de documents html pour être utilisé par le javascript côté client.

mise à jour : le site original a subi un remaniement, voici la version mise à jour

23
répondu Dan 2011-02-16 19:25:35

Eh bien, cela a déjà un tas de réponses, mais malheureusement il n'y a pas de "vrai" hasard dans le tas. La version ci-dessous est une adaptation de la réponse de broofa, mais mise à jour pour inclure une fonction aléatoire "true" qui utilise les bibliothèques crypto lorsqu'elles sont disponibles, et la fonction Alea() comme un repli.

  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);
  });
};
23
répondu jvenema 2016-04-11 13:51:11

projet JavaScript sur GitHub - https://github.com/LiosK/UUID.js

UUID.js le générateur UUID compatible RFC pour JavaScript.

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

Les caractéristiques

génèrent des UUID conformes à la RFC 4122.

Version 4 UUIDs (UUIDs from nombres aléatoires) et la version 1 UUIDs (UUIDs basés sur le temps) sont disponibles.

UUID objet permet une variété d'accès à L'UUID les champs UUID.

faible résolution temporelle de JavaScript compensée par une résolution aléatoire nombre.

21
répondu Wojciech Bednarski 2012-07-02 21:00:32

cette création version 4 UUID (créé à partir de pseudo nombres aléatoires):

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

voici un échantillon des UUIDs générés:

682db637-0f31-4847-9cdf-25ba9613a75c
97d19478-3ab2-4aa1-b8cc-a1c3540f54aa
2eed04c9-2692-456d-a0fd-51012f947136
20
répondu Mathieu Pagé 2009-08-24 16:12:46
  // 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('-');
16
répondu jablko 2010-07-14 23:30:52

ajusté mon propre générateur UUID/GUID avec quelques extras ici .

j'utilise le Générateur de nombres aléatoires Kybos suivant pour être un peu plus cryptographique.

ci-dessous est mon script avec les méthodes Mash et Kybos de baagoe.com exclu.

//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));
13
répondu Tracker1 2012-01-13 21:59:35

La meilleure façon:

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
 }

minimisé:

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}
12
répondu Andrea Turri 2012-05-23 18:42:35

je voulais comprendre la réponse de broofa, donc je l'ai étendue et ajouté des commentaires:

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);
        }
    );
};
12
répondu Andrew 2017-02-20 14:46:21

c'est juste un simple appel AJAX...

Si quelqu'un est intéressé, voici ma solution.

côté serveur:

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

côté client:

var myNewGuid = null;
PageMethods.GenerateGuid(
    function(result, userContext, methodName)
    {
        myNewGuid = result;
    },
    function()
    {
        alert("WebService call failed.");
    }
);
11
répondu alekop 2010-02-05 03:23:46

pour ceux qui veulent une solution compatible rfc4122 version 4 avec des considérations de vitesse (peu d'appels aux mathématiques.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("");
}

la fonction ci-dessus doit avoir un équilibre décent entre la vitesse et l'aléatoire.

11
répondu John Fowler 2012-11-16 19:41:49

je sais, c'est une vieille question. Pour être complet, si votre environnement est SharePoint, il existe une fonction utilitaire appelée SP.Guid.newGuid ( lien msdn ) qui crée une nouvelle interface graphique. Cette fonction est à l'intérieur du sp.initialisation.fichier js. Si vous réécrire cette fonction (pour supprimer certains autres dépendances d'autres fonctions privées), il ressemble à ceci:

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;
};
10
répondu Anatoly Mironov 2013-06-12 16:00:03

il y a un plugin jQuery qui gère guid's nicely @ http://plugins.jquery.com/project/GUID_Helper

jQuery.Guid.Value()

renvoie la valeur du Guid interne. Si aucun guid n'a été spécifié, renvoie un nouveau (la valeur est alors stockée en interne).


jQuery.Guid.New()

renvoie un nouveau Guid et définit sa valeur en interne.


jQuery.Guid.Empty()

Returns un vide Guid 00000000-0000-0000-0000-000000000000.


jQuery.Guid.IsEmpty()

renvoie booléen. True si vide/non défini/blanc / null.


jQuery.Guid.IsValid()

renvoie booléen. Vrai guide valide, faux si ce n'est pas le cas.


jQuery.Guid.Set()

Retrns Guid. Jeux de Guid de l'utilisateur spécifié Guid, si invalide, renvoie un vide guid.

10
répondu Levitikon 2013-10-09 04:54:35

échantillon ES6

const guid=()=> {
  const s4=()=> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);     
  return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4() + s4() + s4()}`;
}
10
répondu Behnam Mohammadi 2017-07-09 13:01:53

celui-ci est basé sur la date, et ajoute un suffixe aléatoire pour" assurer " l'unicité. Fonctionne bien pour les identificateurs css. Il retourne toujours quelque chose comme et est facile à hacker:

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;
        };
9
répondu ling 2014-03-06 11:34:54

bizarre que personne ne l'ait encore mentionné mais pour être complet, il y a une pléthore de générateurs de guid sur npm je suis prêt à parier que la plupart d'entre eux fonctionnent aussi dans le navigateur.

7
répondu George Mauer 2014-02-03 15:54:16