web-dev-qa-db-fra.com

Créer GUID / UUID en JavaScript?

J'essaie de créer des identificateurs uniques en JavaScript en JavaScript. Je ne sais pas quelles routines sont disponibles sur tous les navigateurs, dans quelle mesure le générateur de nombres aléatoires intégré est "aléatoire", etc.

Le GUID/UUID doit comporter au moins 32 caractères et doit rester dans la plage ASCII pour éviter les problèmes lors de leur transmission.

3519
Jason Cohen

Les UUID (Universally Unique IDentifier), également appelés GUID (Globally Unique IDentifier), selon RFC 4122 , sont des identifiants avec une certaine garantie d'unicité.

La meilleure façon de les générer est de suivre les instructions d'implémentation dans ledit RFC, d'utiliser l'une des nombreuses implémentations open source validées par la communauté ou, pour les langages qui en disposent, d'utiliser l'implémentation intégrée.

Quelques exemples d’outils open source pour travailler avec des UUID, pour certains langages de programmation courants, sont listés ici.

JavaScript

PHP

Aller

Ruby

Python


Notez que le fait de générer de manière aléatoire les identifiants octet par octet ou caractère par caractère ne vous donnera pas les mêmes garanties qu'une implémentation conforme. De plus, il est également très important que les systèmes fonctionnant avec des UUID conformes puissent choisir de ne pas accepter ceux générés aléatoirement, et de nombreux validateurs open source vérifieront en fait la présence d’une structure valide.

Un UUID doit avoir ce format:

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

Les positions M _ et N ne peuvent avoir que certaines valeurs. À l'heure actuelle, les seules valeurs valides pour M sont 1, 2, 3, 4 et 5, donc générer cette position de manière aléatoire rendrait la plupart des résultats inacceptables.

2098
John Millikin

Pour une solution conforme à la version 4 RFC4122 , cette solution one-liner (ish) est la plus compacte que je puisse 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())

Update, 2015-06-02 : sachez que l'unicité des UUID dépend fortement du générateur de nombres aléatoires sous-jacent (GNA). La solution ci-dessus utilise Math.random() par souci de brièveté. Cependant, Math.random() n’est pas garanti d’être un GNA de haute qualité. Voir excellente rédaction d'Adam Hyland sur Math.random () pour plus de détails. Pour une solution plus robuste, envisagez quelque chose comme le module uuid [Avertissement: je suis l'auteur], qui utilise des API RNG de meilleure qualité, le cas échéant.

Update, 2015-08-26 : En remarque, ceci Gist décrit comment déterminer combien d'identifiants peuvent être générés avant d'atteindre une certaine probabilité de collision. Par exemple, avec 3.26x1015 version 4 UFID RFC4122, vous avez 1 chance sur 1 000 de collision.

Mise à jour du 2017-06-28 : A bon article de Chrome développeurs discuter de l'état de Math.random PRNG dans Chrome, Firefox et Safari. tl; dr - À la fin de 2015, la qualité est "plutôt bonne", mais pas la qualité cryptographique. Pour résoudre ce problème, voici une version mise à jour de la solution ci-dessus qui utilise ES6, l'API crypto et un peu de l'assistant JS pour lequel je ne peux pas prendre crédit :

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

J'aime vraiment la propreté la réponse de Broofa est, mais il est regrettable que de mauvaises applications de Math.random laissent la chance à une collision. 

Voici une solution similaire RFC4122 version 4 qui résout ce problème en décalant les 13 premiers nombres hexadécimaux d’une partie hexadécimale de l’horodatage. Ainsi, même si Math.random est sur la même graine, les deux clients devraient générer l'UUID exactement à la même milliseconde (ou 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.

726
Briguy37

la réponse de broofa est plutôt astucieuse: une habileté impressionnante, vraiment ... conforme à la norme rfc4122, plutôt lisible et compacte. Impressionnant!

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

Mais pouvons-nous obtenir la vitesse et conformité RFC? Je dis oui! Pouvons-nous maintenir la lisibilité? Eh 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 à la variable non conforme à la 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.

Ainsi, à la sixième itération d'optimisations, j'ai battu la réponse la plus populaire de plus de 12X, la réponse acceptée de plus de 9X et la réponse rapide non conforme de 2-3X. Et je suis toujours conforme à la norme RFC4122.

Intéressé par comment? J'ai mis le code complet sur http://jsfiddle.net/jcward/7hyaC/3/ et sur http://jsperf.com/uuid-generator-opt/4

Pour une explication, commençons par 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);
});

Donc, il remplace x par tout chiffre hexadécimal aléatoire, y par des données aléatoires (sauf en forçant les 2 premiers bits à 10 conformément à la spécification RFC), et la regex ne correspond pas aux caractères - ou 4, de sorte qu'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, de même que les expressions régulières (bien qu'il n'en utilise qu'un, il a 32 rappels, un pour chaque correspondance, et dans chacun des 32 rappels, il appelle Math.random () et v. toString (16)).

La première étape vers la performance consiste à éliminer le RegEx et ses fonctions de rappel et à utiliser une simple boucle. Cela signifie que nous devons traiter avec les caractères - et 4, contrairement à broofa. Notez également que nous pouvons utiliser l'indexation sur tableau de chaînes pour conserver son architecture de modèle de chaîne lisse:

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 - ou 4, et l’utilisation d’une boucle while (au lieu de rappels replace()) nous procure une amélioration presque de 3X!

La prochaine étape est un petit sur le bureau, mais fait une différence décente sur mobile. Faisons moins d'appels Math.random () et utilisons tous ces bits aléatoires au lieu d'en jeter 87% avec un tampon aléatoire décalé à chaque itération. Déplaçons également cette définition de modèle en dehors de la boucle, au cas où cela aiderait:

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 épargne 10-30% selon la plate-forme. Pas mal. Mais la prochaine étape importante consiste à supprimer les appels de la fonction toString avec un classique de l'optimisation: la table de correspondance. Une table de consultation simple de 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 gérons 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 toujours gérer les positions de bits conformes à RFC, mais ce n'est pas trop difficile. Nous devons ensuite créer une table de consultation plus grande (16x16 ou 256) pour stocker 0x00 - 0xff et nous ne la construisons qu’une 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, en utilisant toujours la LUT à 256 éléments, et il a montré les rendements décroissants de l'optimisation. Bien qu’elle ait eu moins d’itérations, la logique interne a été compliquée par l’augmentation du traitement. Elle s’est comportée de la même manière sur les ordinateurs de bureau, et seulement environ 10% plus rapide sur les appareils mobiles.

La technique d'optimisation finale à appliquer - dérouler la boucle. Étant donné que nous bouclons un nombre fixe de fois, nous pouvons techniquement écrire tout cela à la main. J'ai essayé cela une fois avec une seule variable aléatoire r que je réassignais sans cesse, et dont la performance était optimisée. Mais avec quatre variables assignées de manière aléatoire à l’avance, puis en utilisant la table de recherche et en appliquant les bits RFC appropriés, cette version les enfume toutes:

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

La chose amusante est que générer 16 octets de données aléatoires est la partie la plus facile. Toute l'astuce consiste à l'exprimer au format String avec la conformité RFC, et le plus précisément avec 16 octets de données aléatoires, une boucle déroulée et une table de recherche.

J'espère que ma logique est correcte - il est très facile de se tromper dans ce genre de travail fastidieux. Mais les sorties me semblent bonnes. J'espère que vous avez apprécié cette course folle grâce à 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 véritablement aléatoires, qui sont importants pour générer de bons UUID.

353
Jeff Ward

Voici un code basé sur RFC 4122 , section 4.4 (Algorithmes pour la création d’un UUID à partir d’un nombre véritablement 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;
}
142
Kevin Hakanson

Le plus rapide GUID comme méthode du générateur de chaînes au format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. Cela ne génère pas de GUID conforme aux normes.

Dix millions d'exécutions de cette implémentation ne prennent que 32,5 secondes, ce qui est le 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 ([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();
}

Pour tester les performances, 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 au moins une personne aura-t-elle besoin d’une explication:

L'algorithme:

  • La fonction Math.random() renvoie un nombre décimal compris entre 0 et 1 et 16 chiffres après le point décimal (par exemple 0.4363923368509859).
  • Ensuite, nous prenons ce nombre et le convertissons en une chaîne de base 16 (à partir de l'exemple ci-dessus, nous aurons 0.6fb7687f).
    Math.random().toString(16).
  • Ensuite, nous coupons le préfixe 0. (0.6fb7687f => 6fb7687f) et obtenons une chaîne de huit caractères hexadécimaux.
    (Math.random().toString(16).substr(2,8).
  • Parfois, la fonction Math.random() retournera un nombre plus court (par exemple 0.4363), en raison de zéros à la fin (d'après l'exemple ci-dessus, le nombre est en fait 0.4363000000000000). C'est pourquoi j'ajoute à cette chaîne "000000000" (une chaîne de neuf zéros), puis la coupe avec la fonction substr() pour en faire exactement neuf caractères (les zéros remplis à droite).
  • La raison pour ajouter exactement neuf zéros est due au pire des cas, c'est-à-dire lorsque la fonction Math.random() renverra exactement 0 ou 1 (probabilité de 1/10 ^ 16 pour chacun d'eux). C'est pourquoi nous avons dû lui ajouter neuf zéros ("0"+"000000000" ou "1"+"000000000"), puis le couper du deuxième index (3ème caractère) d'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 GUID est au format suivant XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.
  • J'ai divisé le GUID en 4 morceaux, chaque morceau étant divisé en 2 types (ou formats): XXXXXXXX et -XXXX-XXXX.
  • Maintenant, je construis le GUID en utilisant ces 2 types pour assembler le GUID avec l'appel 4 pièces, comme suit: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.
  • Pour différencier ces deux types, j'ai ajouté un paramètre d'indicateur à une fonction créateur de paire _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 retournons.

Lien vers ce post sur mon blog

Profitez-en! : -)

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

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

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

Si deux ID sont générés à des intervalles plus rapprochés et en supposant que la méthode aléatoire soit réellement aléatoire, cela générera des ID à 99,99999999999999% susceptibles d'être globalement uniques (collision dans 1 sur 10 ^ 15)

Vous pouvez augmenter ce nombre en ajoutant plus de chiffres, mais pour générer 100% d'identifiants uniques, vous devez utiliser un compteur global.

si vous avez vraiment besoin de la conformité RFC, cette mise en forme sera transmise comme un GUID de version 4 valide:

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

var r = (new Date()).getTime().toString(16) + Math.random().toString(16).substring(2) + "0".repeat(16);
var guid = r.substr(0,8) + '-' + r.substr(8,4) + '-4000-8' + r.substr(12,3) + '-' + r.substr(15,12);
document.getElementById("unique").innerHTML = guid;
<div id="unique">
</div>

Edit: Le code ci-dessus suit l'intention, mais pas la lettre du RFC. Parmi les différences, il ne reste que quelques chiffres aléatoires. (Ajoutez plus de chiffres aléatoires si vous en avez besoin) L'avantage, c'est que c'est très rapide, comparé à 100% de code conforme . Vous pouvez tester votre GUID ici

81
Simon Rigét

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

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

On jsbin si vous voulez le tester.

60
ripper234

Voici une solution datée du 9 octobre 2011 d'un commentaire de l'utilisateur jed à l'adresse 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 la mieux notée actuellement }, mais dans au moins 50 octets en moins, en exploitant la contrainte, la récursivité et la notation exponentielle. Pour ceux qui sont curieux de savoir 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
      )
}
55
Jed Schmidt

Voici une implémentation totalement non conforme mais très performante permettant de générer un identifiant unique de type GUID conforme à la norme ASCII.

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], générant un UID à la fois plus court et plus unique que les GUID compatibles RFC. Des tirets peuvent être ajoutés de manière triviale si la lisibilité est importante.

Voici des exemples d’utilisation et des horaires pour cette fonction, ainsi que plusieurs autres réponses de cette question. La synchronisation a été effectuée sous Chrome m25, 10 millions d'itérations chacune.

>>> 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 chronométrage.

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

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

Génération simple et rapide de RFC4122 UUIDS.

Caractéristiques:

  • Générer des UUID RFC4122 version 1 ou version 4
  • S'exécute dans node.js et les navigateurs.
  • Génération aléatoire # cryptographique forte sur les plates-formes de support.
  • Faible encombrement (Vous voulez quelque chose de plus petit? Vérifiez ceci! )

Installer à l'aide de 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 le fichier Raw (uuid v4): https: // raw.githubusercontent.com/kelektiv/node-uuid/master/v4.js


Vous voulez encore plus petit? Découvrez ceci: 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();
32
Kyros Koh

De le blog technique de sagi shkedy :

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 existe d'autres méthodes qui impliquent l'utilisation d'un contrôle ActiveX, mais restez à l'écart de celles-ci!

Edit: J'ai pensé qu'il valait la peine de signaler qu'aucun générateur GUID ne peut garantir des clés uniques (consultez l'article de wikipedia ). Il y a toujours une chance de collision. Un GUID offre simplement un univers de clés suffisamment grand pour réduire à néant le changement de collision.

31
Prestaul

Un service Web serait utile. 

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

Vous ne pouvez pas vous porter garant de cette implémentation, mais QUELQU'UN doit publier un générateur GUID de bonne foi.

Avec un tel service Web, vous pouvez développer une interface Web REST qui utilise le service Web GUID et la sert via AJAX à JavaScript dans un navigateur.

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

MODIFIER:

Revisité mon projet qui utilisait cette fonction et n'aimait pas la verbosité. - Mais besoin d'un bon hasard.

Une version basée sur la réponse de Briguy37 et quelques opérateurs au niveau des bits permettant d'extraire des fenêtres de la taille d'un quartet à partir du tampon.

Devrait adhérer au schéma RFC Type 4 (aléatoire), car la dernière fois que je rencontrais des problèmes, j'analysais des uuids non conformes avec l'UUID de Java.

29
sleeplessnerd

Module JavaScript simple combinant les 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());

Usage: 

Guid.newGuid ()

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

Guid.empty

"00000000-0000-0000-0000-000000000000"

28
kayz1

De 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 amélioré en salant avec un hachage de l'adresse IP du client. Ce hachage pourrait peut-être être inséré dans le document html côté serveur pour être utilisé par le javascript côté client.

MISE À JOUR: Le site d'origine a été modifié, voici la version mise à jour

23
Dan

Eh bien, cela a déjà un tas de réponses, mais malheureusement, il n’ya pas de "vrai" hasard dans le peloton. La version ci-dessous est une adaptation de la réponse de broofa, mais mise à jour pour inclure une "vraie" fonction aléatoire qui utilise des bibliothèques de chiffrement, le cas échéant, et la fonction Alea () comme solution de secours.

  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 <[email protected]>, 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 <[email protected]>, 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
jvenema

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

UUID.js Le générateur UUID conforme à RFC pour JavaScript.

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

Features Génère des UUID conformes à la norme RFC 4122.

UUID de la version 4 (UUID de nombres aléatoires) et UUID de la version 1.. (UUID temporels) sont disponibles.

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

La résolution d'horodatage faible de JavaScript est compensée par aléatoire Nombres.

21
Wojciech Bednarski

Ceci crée la version 4 UUID (créée à partir de nombres pseudo 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 exemple des UUID générés:

682db637-0f31-4847-9cdf-25ba9613a75c
97d19478-3ab2-4aa1-b8cc-a1c3540f54aa
2eed04c9-2692-456d-a0fd-51012f947136
20
Mathieu Pagé
  // 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
jablko

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 sain sur le plan cryptographique.

Ci-dessous mon script avec les méthodes Mash et Kybos de baagoe.com exclus.

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

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

Je voulais comprendre la réponse de Broofa, alors je l'ai développée 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
Andrew

É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()}`;
}
11
Behnam Mohammadi

C'est juste un simple appel AJAX ...

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

Du côté du serveur:

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

Du côté du client:

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

Pour ceux qui recherchent une solution compatible rfc4122 version 4 avec des considérations de rapidité (quelques appels à 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("");
}

La fonction ci-dessus devrait avoir un bon équilibre entre vitesse et caractère aléatoire.

11
John Fowler

Il existe un plugin jQuery qui gère gentiment @ http://plugins.jquery.com/project/GUID_Helper

jQuery.Guid.Value()

Retourne la valeur de Guid interne. Si aucun guid n'a été spécifié, retourne 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()

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


jQuery.Guid.IsEmpty()

Retourne booléen. Vrai si vide/indéfini/vierge/null.


jQuery.Guid.IsValid()

Retourne booléen. Vrai guide valide, faux sinon.


jQuery.Guid.Set()

Retrns Guid. Définit Guid sur l'utilisateur spécifié. Guid, s'il est invalide, renvoie un GUID vide.

10
Levitikon

Je sais, c'est une vieille question. Juste pour être complet, si votre environnement est SharePoint, il existe une fonction utilitaire appelée SP.Guid.newGuid ( msdn link ) qui crée un nouveau GUID. Cette fonction se trouve dans le fichier sp.init.js. Si vous réécrivez cette fonction (pour supprimer d'autres dépendances d'autres fonctions privées), cela 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
Anatoly Mironov

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

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
ling

Code simple utilisant crypto.getRandomValues(a) sur navigateurs pris en charge (IE11 +, iOS7 +, FF21 +, Chrome, Android Chrome). Evite d'utiliser Math.random() car cela peut provoquer des collisions (par exemple 20 collisions pour 4000 uuids générés en situation réelle par 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);
}

Remarques:

  • Optimisé pour la lisibilité du code, pas pour la vitesse, convient donc pour quelques centaines d’uuidés par seconde. Génère environ 10 000 uuid () par seconde en chrome sur mon ordinateur portable à l’aide de http://jsbin.com/fuwigo/1 pour mesurer les performances.
  • Utilise uniquement 8 pour "y" car cela simplifie la lisibilité du code (y est autorisé à être 8, 9, A ou B).
6
robocat

Si vous avez juste besoin d'une chaîne aléatoire de 128 bits sans format particulier, vous pouvez utiliser:

function uuid() {
    return crypto.getRandomValues(new Uint32Array(4)).join('-');
}

Ce qui retournera quelque chose comme 2350143528-4164020887-938913176-2513998651.

6
Jonathan Potter

Il est important d’utiliser du code bien testé et maintenu par plus d’un contributeur au lieu de fouetter vos propres données pour cela. C’est l’un des endroits où vous préférez probablement le code le plus stable que la version la plus courte et intelligente qui fonctionne dans le navigateur X mais ne tient pas compte des particularités du compte de Y, ce qui conduit souvent à des problèmes d’investigation beaucoup plus difficiles que de ne manifester que de manière aléatoire pour certains utilisateurs. Personnellement, j'utilise uuid-js à https://github.com/aurigadl/uuid-js qui est activé par bower pour que je puisse prendre facilement les mises à jour.

5
Shital Shah

Juste une autre variante plus lisible avec seulement deux mutations.

function uuid4()
{
  function hex (s, b)
  {
    return s +
      (b >>> 4   ).toString (16) +  // high nibble
      (b & 0b1111).toString (16);   // low nibble
  }

  let r = crypto.getRandomValues (new Uint8Array (16));

  r[6] = r[6] >>> 4 | 0b01000000; // Set type 4: 0100
  r[8] = r[8] >>> 3 | 0b10000000; // Set variant: 100

  return r.slice ( 0,  4).reduce (hex, '' ) +
    r.slice ( 4,  6).reduce (hex, '-') +
    r.slice ( 6,  8).reduce (hex, '-') +
    r.slice ( 8, 10).reduce (hex, '-') +
    r.slice (10, 16).reduce (hex, '-');
}
5
ceving

J'utilise cette fonction ci-dessous, j'espère que cela pourra être utile.

    function NewGuid()
         {
           var sGuid="";
           for (var i=0; i<32; i++)
            {
              sGuid+=Math.floor(Math.random()*0xF).toString(0xF);
            }
           return sGuid;
         }
3
Giridhar

Vous pouvez utiliser le package npm guid, un générateur et un validateur de guides.

https://www.npmjs.com/package/guid

Exemple:

Guid.raw();
// -> '6fdf6ffc-ed77-94fa-407e-a7b86ed9e59d'

UPDATE: Ce paquet est obsolète. Utilisez uuid à la place. 

https://www.npmjs.com/package/uuid

Exemple: 

const uuidv4 = require('uuid/v4');
uuidv4(); // ⇨ '10ba038e-48da-487b-96e8-8d3b99b6d18a'
3
andersh

Juste au cas où les utilisateurs de Google rechercheraient une petite bibliothèque d’utilitaires, ShortId ( https://www.npmjs.com/package/shortid ) répond à toutes les exigences de cette question. Il permet de spécifier les caractères et la longueur autorisés et garantit des chaînes non séquentielles et non répétitives.

Pour en faire une vraie réponse, le noyau de cette bibliothèque utilise la logique suivante pour produire ses identifiants courts:

function encode(lookup, number) {
    var loopCounter = 0;
    var done;

    var str = '';

    while (!done) {
        str = str + lookup( ( (number >> (4 * loopCounter)) & 0x0f ) | randomByte() );
        done = number < (Math.pow(16, loopCounter + 1 ) );
        loopCounter++;
    }
    return str;
}

/** Generates the short id */
function generate() {

    var str = '';

    var seconds = Math.floor((Date.now() - REDUCE_TIME) * 0.001);

    if (seconds === previousSeconds) {
        counter++;
    } else {
        counter = 0;
        previousSeconds = seconds;
    }

    str = str + encode(alphabet.lookup, version);
    str = str + encode(alphabet.lookup, clusterWorkerId);
    if (counter > 0) {
        str = str + encode(alphabet.lookup, counter);
    }
    str = str + encode(alphabet.lookup, seconds);

    return str;
}

Je n'ai pas modifié cela pour refléter uniquement les parties les plus élémentaires de cette approche. Le code ci-dessus inclut donc une logique supplémentaire issue de la bibliothèque. Si vous êtes curieux de tout ce que vous faites, jetez un oeil à la source: https://github.com/dylang/shortid/tree/master/lib

3
MaxPRafferty

J'ai trouvé ce script utile pour créer des GUID en JavaScript

https://github.com/addui/GUIDJS

var myGuid = GUID();
3
Dustin Poissant

Pour ceux qui utilisent Javascript sous Windows (par exemple, WScript/CScript/MSHTA). On peut utiliser ActiveX. Plus précisément, l'objet Scriptlet.Typelib:

WScript.Echo((new ActiveXObject("Scriptlet.TypeLib")).Guid)

Notez que cette réponse ne fonctionne que sur les technologies que j'ai énumérées, elle ne fonctionnera pas avec les navigateurs, pas même Microsoft Edge! Votre kilométrage variera donc avec cette réponse.

2
Stephen Quan

Pour mon cas d'utilisation, j'avais besoin d'une génération d'identifiant qui était garantie d'être unique au monde; sans exception. J'ai eu du mal à résoudre le problème pendant un moment et j'ai proposé une solution appelée tuid (ID vraiment unique). Il génère un identifiant avec les 32 premiers caractères générés par le système et les chiffres restants représentant des millisecondes depuis Epoch. Dans les cas où j'ai besoin de générer des identifiants sur du javascript côté client, cela fonctionne bien. Regarde:

https://github.com/mongoh/tuid

2
Rishi

Bonjour, voici un exemple de travail qui génère un UUID unique à 32 chiffres. 

function generateUUID() {
      var d = new Date();
      var k = d.getTime();
     var str = k.toString(16).slice(1)
    var UUID= 'xxxx-xxxx-4xxx-yxxx-xzx'.replace(/[xy]/g, function (c)
      {
        var r = Math.random() * 16 | 0;
        v = c == 'x' ? r : (r & 3 | 8);
        return v.toString(16);
      });
      var newString = UUID.replace(/[z]/, str)
      return newString;
    }
    var x = generateUUID()
    console.log(x,x.length)
2
Ashish Yadav

Je ne pouvais trouver aucune réponse utilisant un seul nom TypedArray et DataView de 16 octets. Je pense donc que la solution suivante pour générer un UUID de version 4 par le RFC sera autonome:

function uuid4() {
    const ho = (n, p) => n.toString(16).padStart(p, 0); /// Return the hexadecimal text representation of number `n`, padded with zeroes to be of length `p`
    const view = new DataView(new ArrayBuffer(16)); /// Create a view backed by a 16-byte buffer
    crypto.getRandomValues(new Uint8Array(view.buffer)); /// Fill the buffer with random data
    view.setUint8(6, (view.getUint8(6) & 0xf) | 0x40); /// Patch the 6th byte to reflect a version 4 UUID
    view.setUint8(8, (view.getUint8(8) & 0x3f) | 0x80); /// Patch the 8th byte to reflect a variant 1 UUID (version 4 UUIDs are)
    return `${ho(view.getUint32(0), 8)}-${ho(view.getUint16(4), 4)}-${ho(view.getUint16(6), 4)}-${ho(view.getUint16(8), 4)}-${ho(view.getUint32(10), 8)}${ho(view.getUint16(14), 4)}`; /// Compile the canonical textual form from the array data
}

Je le préfère car il ne s'appuie que sur les fonctions disponibles sur la plate-forme ECMAScript standard.

1
amn

sur la base du travail de broofa, j’ai ajouté un peu plus de caractère aléatoire en ajoutant l’horodatage à math.random () 

J'espère que ça pourrait aider

function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = parseFloat('0.' + Math.random().toString().replace('0.', '') + new Date().getTime()) * 16 | 0,
            v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}
1
freecloud

Vous trouverez ici une très petite fonction qui génère uuids https://Gist.github.com/jed/982883

Une des versions finales est:

function b(
  a                  // placeholder
){
  var cryptoObj = window.crypto || window.msCrypto; // for IE 11
  return a           // if the placeholder was passed, return
    ? (              // a random number from 0 to 15
      a ^            // unless b is 8,
      cryptoObj.getRandomValues(new Uint8Array(1))[0]  // 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
      )
}
1
Pablo Pazos

Une solution simple pour générer une identification unique consiste à utiliser un jeton de temps et à lui ajouter un nombre aléatoire. Je préfère le préfixer par "uuid-".

La fonction ci-dessous générera une chaîne aléatoire de type: uuid-14d93eb1b9b4533e6 . Il n'est pas nécessaire de générer une chaîne aléatoire de 32 caractères. Une chaîne aléatoire de 16 caractères est plus que suffisante dans ce cas pour fournir les UUID uniques en javascript.

 var createUUID = function () {
 renvoie "uuid -" + ((nouvelle date) .getTime (). toString (16) + Math.floor (1E7 * Math.random ()). toString (16));
0
mangalbhaskar

OK, en utilisant le package uuid, il prend en charge les UUID version 1, 3, 4 et 5

yarn add uuid

et alors:

const uuidv1 = require('uuid/v1');
uuidv1(); // ⇨ '45745c60-7b1a-11e8-9c9c-2d42b21b1a3e'

Vous pouvez également le faire avec des options entièrement spécifiées:

const v1options = {
  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
  clockseq: 0x1234,
  msecs: new Date('2011-11-01').getTime(),
  nsecs: 5678
};
uuidv1(v1options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab'

Pour plus d’informations, visitez la page npm ici

0
Alireza

Je pensais juste que je publierais encore une autre façon de faire la même chose.

function guid() {
  var chars = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"];
  var str = "";
  for(var i=0;i<36;i++) {
    var str = str + ((i == 8 || i == 13 || i == 18 || i == 23) ? "-" : chars[Math.floor(Math.random()*chars.length)]);
  };
  return str;
}
0
Matthew Riches

Cela peut être utile à quelqu'un ...

var d = new Date().valueOf();
var n = d.toString();
var result = '';
var length = 32;
var p = 0;
var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

for (var i = length; i > 0; --i){
    result += ((i & 1) && n.charAt(p) ? '<b>' + n.charAt(p) + '</b>' : chars[Math.floor(Math.random() * chars.length)]);
    if(i & 1) p++;
};

https://jsfiddle.net/j0evrdf1/1/

0
lugreen
function randomHex(length) {
    var random_string = '';
    if(!length){
        length = 1;
    }
    for(var i=0; i<length; i+=1){
        random_string += Math.floor(Math.random() * 15).toString(16);
    }
    return random_string;
}

function guid() {
    return randomHex(8);
}
0
JHG

Nous pouvons utiliser replace et crypto.getRandomValues ​​pour obtenir une sortie comme celle-ci:

xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx

 enter image description here

Si nous recherchons une solution opti, nous devons remplacer crypto.getRandomValues(new Uint8Array(1))[0] par un tableau (32).

const uuidv4 = () =>
  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  );

console.log(uuidv4());

Pour obtenir ce code:

function uuidv4() {
  let bytes = window.crypto.getRandomValues(new Uint8Array(32));
  const randomBytes = () => (bytes = bytes.slice(1)) && bytes[0];

  return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => 
      (c ^ randomBytes() & 15 >> c / 4).toString(16)
    );
}


for (var i = 0; i < 10; i++)
  console.log(uuidv4());

Collision:

Nous pouvons faire comme Google Analytics et ajouter un horodatage avec: uuidv4() + "." + (+new Date()).

0
A-312

Pour la science. Je n'ai encore vu personne faire cela ... ce n'est pas conforme à la v4, mais pourrait facilement être modifié. C'est juste un exemple d'extension du type Uint8Array et d'utilisation de crypto.getRandomValues ​​() pour générer les valeurs d'octets uuid.

class uuid extends Uint8Array {
        constructor() {
            super(16)
            /* not v4, just some random bytes */
            window.crypto.getRandomValues(this)
        }
        toString() {
            let id = new String()
            for (let i = 0; i < this.length; i++) {
                /*convert uint8 to hex string */
                let hex = this[i].toString(16).toUpperCase()

                /*add zero padding*/
                while (hex.length < 2) {
                    hex = String(0).concat(hex)
                }
                id += hex

                /* add dashes */
                if (i == 4 || i == 6 || i == 8 || i == 10 || i == 16){
                    id += '-'
                }
            }
            return id
        }
    }
0
Jacob Ochoa