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.
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"/>
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());
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);
});
}
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.
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;
}
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 exemple0.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 exemple0.4363
), en raison de zéros à la fin (à partir de l'exemple ci-dessus, en fait le nombre est0.4363000000000000
). C'est pourquoi j'ajoute à cette chaîne"000000000"
(une chaîne avec neuf zéros) et je la coupe ensuite avec la fonctionsubstr()
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ètres
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! :- )
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>
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.
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
)
}
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');
à 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.
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.
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.
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"
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();
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
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);
});
};
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éristiquesgé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.
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
// 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('-');
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));
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}
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);
}
);
};
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.");
}
);
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.
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;
};
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.
é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()}`;
}
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;
};
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.