Я пытаюсь создать глобально уникальные идентификаторы в JavaScript. Я не уверен, какие подпрограммы доступны во всех браузерах, как "случайные" и засеянные встроенным генератором случайных чисел, и т.д.
Идентификатор GUID/UUID должен быть не менее 32 символов и должен оставаться в диапазоне ASCII, чтобы избежать проблем при их передаче.
UUID (универсальный уникальный идентификатор), также известный как GUID (глобальный уникальный идентификатор), согласно RFC 4122, являются идентификаторами с определенной гарантией уникальности.
Лучший способ их генерирования - следовать инструкциям по реализации в указанном RFC, использовать одну из многих проверенных реализаций с открытым исходным кодом или использовать встроенную реализацию для языков, в которых она есть.
Некоторые примеры инструментов с открытым исходным кодом для работы с UUID, для некоторых популярных языков программирования перечислены здесь.
JavaScript
PHP
Идти
Рубин
питон
Обратите внимание, что просто случайная генерация идентификаторов побайтово или посимвольно не даст вам таких же гарантий, как соответствующая реализация. Кроме того, очень важно, что системы, работающие с совместимыми UUID, могут не принимать случайно сгенерированные, и многие валидаторы с открытым исходным кодом на самом деле проверяют правильность структуры.
UUID должен иметь этот формат:
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
Где позиции M и N могут иметь только определенные значения. В настоящее время единственными допустимыми значениями для M являются 1, 2, 3, 4 и 5, поэтому случайная генерация этой позиции сделает большинство результатов неприемлемыми.
Для решения RFC4122 версии 4 это однострочное (ish) решение является самым компактным, с которым я мог бы справиться.
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())
Обновление, 2015-06-02. Имейте в виду, что уникальность UUID в значительной степени зависит от базового генератора случайных чисел (RNG). В приведенном выше решении для краткости используется Math.random()
, однако Math.random()
не гарантированно является высококачественным RNG. Подробнее см. Adam Hyland отличную запись на Math.random(). Для более надежного решения рассмотрите что-то вроде uuid module [Отказ от ответственности: я автор], который использует более качественные API-интерфейсы RNG, если таковые имеются.
Обновление, 2015-08-26. В качестве примечания этот gist описывает, как определить, сколько идентификаторов может быть сгенерировано до достижения определенной вероятности столкновения. Например, при использовании UUID с частотой 3.26x10 15 версии 4 RFC4122 у вас есть вероятность столкновения 1-в-миллион.
Обновление, 2017-06-28: хорошая статья разработчиков Chrome, обсуждающая состояние Math.random Качество PRNG в Chrome, Firefox и Safari. tl; dr - По состоянию на конец 2015 года это "очень хорошо", но не криптографическое. Чтобы решить эту проблему, здесь приведена обновленная версия вышеупомянутого решения, которое использует ES6, API crypto
и немного JS wizardy. Я не могу взять кредит для:
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());
Мне очень нравится, насколько чистый ответ Бройфа, но, к сожалению, плохие реализации Math.random
оставляют шанс на столкновение.
Здесь аналогичное решение, совместимое с RFC4122 версии 4, которое решает эту проблему, компенсируя первые 13 шестнадцатеричных чисел шестнадцатеричной частью метки времени. Таким образом, даже если Math.random
находится на одном семестре, оба клиента должны будут сгенерировать UUID с той же миллисекунды (или 10, 000+ лет спустя), чтобы получить тот же 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);
});
}
new Date().getTime()
не обновляется каждую миллисекунду. Я не уверен, как это влияет на ожидаемую случайность вашего алгоритма.
Date.now()
для new Date().getTime()
Ответ на броуф довольно гладкий, действительно - впечатляюще умный, действительно... rfc4122 совместимый, несколько читаемый и компактный. Потрясающие!
Но если вы смотрите на что регулярное выражение, те много replace()
обратные вызовы, toString()
и Math.random()
вызовы функций (где он только с использованием 4 бита результата и растрачивая остальное), вы можете начать задаваться вопросом о качестве. Действительно, joelpt даже решил выбросить RFC для общей скорости GUID с помощью generateQuickGUID
.
Но можем ли мы получить скорость и соответствие RFC? Я говорю да! Можем ли мы поддерживать читаемость? Ну... Не совсем, но это легко, если вы последуете за ним.
Но во- первых, мои результаты, по сравнению с broofa, guid
(принятый ответ), а также не-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.
Итак, на моей 6-й итерации оптимизаций я обыграл самый популярный ответ более чем на 12X, принятый ответ более чем на 9X и быстрый ответ, не отвечающий требованиям 2-3X. И я все еще совместим с rfc4122.
Заинтересованы в том, как? Я поместил полный источник на http://jsfiddle.net/jcward/7hyaC/3/ и на http://jsperf.com/uuid-generator-opt/4
Для пояснения позвольте начать с кода брофы:
'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);
});
Таким образом, он заменяет x
любой случайной шестнадцатеричной цифрой, y
со случайными данными (за исключением того, что верхние 2 бита до 10
в спецификации RFC), а регулярное выражение не совпадает с -
или 4
символами, поэтому ему не нужно иметь дело с ними. Очень, очень гладкий.
Первое, что нужно знать, это то, что вызовы функций дороги, как и регулярные выражения (хотя он использует только 1, он имеет 32 обратных вызова, по одному для каждого совпадения и в каждом из 32 обратных вызовов он вызывает Math.random() и v. ToString (16)).
Первым шагом к производительности является устранение RegEx и его функций обратного вызова и использование простого цикла. Это означает, что мы должны иметь дело с -
и 4
символами, в то время как брофа - нет. Кроме того, обратите внимание, что мы можем использовать индексирование String Array, чтобы сохранить его гладкую структуру шаблонов String:
function e1() {
var u='',i=0;
while(i++<36) {
var c='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'[i-1],r=Math.random()*16|0,v=c=='x'?r:(r&0x3|0x8);
u+=(c=='-'||c=='4')?c:v.toString(16)
}
return u;
}
В принципе, та же внутренняя логика, за исключением проверки -
или 4
, и использование цикла while (вместо обратных вызовов replace()
) дает нам почти 3-кратное улучшение!
Следующий шаг - маленький на рабочем столе, но на мобильных телефонах есть приличная разница. Позвольте сделать меньше вызовов Math.random() и использовать все эти случайные биты вместо того, чтобы отбросить 87% из них со случайным буфером, который смещается с каждой итерации. Пусть также перемещает это определение шаблона из цикла, на всякий случай это помогает:
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
}
Это экономит нам 10-30% в зависимости от платформы. Неплохо. Но следующий большой шаг избавляет от вызовов функции toString вообще с классикой оптимизации - справочной таблицей. Простая 16-элементная таблица поиска будет выполнять задачу toString (16) за гораздо меньшее время:
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
}
Следующая оптимизация - еще одна классика. Поскольку мы обрабатываем только 4-разрядные выходные данные в каждой итерации цикла, позвольте сократить количество циклов пополам и обработать 8-битов на каждой итерации. Это сложно, поскольку нам все еще приходится обрабатывать позиции бит, совместимые с RFC, но это не слишком сложно. Затем нам нужно сделать большую таблицу поиска (16x16 или 256) для хранения 0x00 - 0xff, и мы создадим ее только один раз, вне функции 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
}
Я попробовал e6(), который обрабатывает 16 бит за раз, все еще используя LUT с 256 элементами, и показал снижение прибыли оптимизации. Хотя в нем было меньше итераций, внутренняя логика осложнялась увеличением обработки, и она выполнялась на рабочем столе, и только на 10% быстрее на мобильных устройствах.
Окончательный метод оптимизации для применения - развернуть цикл. Поскольку мы зацикливаемся фиксированным числом раз, мы можем технически написать все это вручную. Я попробовал это один раз с помощью одной случайной переменной r, которую я продолжал переустанавливать, и производительность танков. Но с четырьмя переменными назначались случайные данные спереди, затем, используя таблицу поиска и применяя правильные биты RFC, эта версия курит их все:
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];
}
Модифицировано: http://jcward.com/UUID.js - UUID.generate()
Самое забавное: генерировать 16 байт случайных данных - это легкая часть. Весь трюк выражает его в формате String с соблюдением RFC, и он наиболее сильно выполняется с 16 байтами случайных данных, развернутым циклом и поисковой таблицей.
Надеюсь, моя логика правильная - очень легко ошибиться в такой утомительной работе. Но результаты выглядят хорошо для меня. Надеюсь, вам понравилась эта безумная поездка через оптимизацию кода!
Будьте внимательны: моя главная цель - показать и научить потенциальным стратегиям оптимизации. Другие ответы охватывают важные темы, такие как столкновения и действительно случайные числа, которые важны для создания хороших UUID.
e5
при объединении в 8 бит вы пропускаете 4 бит в части -4xxx-
: вы только что получили ...,'-','4','x','-',...
Или я что-то упустил? Помимо этого +1 для измерения производительности.
Здесь приведен код, основанный на RFC 4122, раздел 4.4 (Алгоритмы создания UUID от действительно случайного или псевдослучайного номера).
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;
}
Самый быстрый GUID, как метод строкового генератора в формате XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
. Это не генерирует стандартный GUID.
Десять миллионов выполнений этой реализации занимают всего 32,5 секунды, что является самым быстрым, что я когда-либо видел в браузере (единственное решение без циклов/итераций).
Функция так же проста, как:
/**
* 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();
}
Чтобы проверить производительность, вы можете запустить этот код:
console.time('t');
for (var i = 0; i < 10000000; i++) {
guid();
};
console.timeEnd('t');
Я уверен, что большинство из вас поймет, что я там делал, но, возможно, есть хотя бы один человек, которому понадобится объяснение:
Алгоритм:
Math.random()
возвращает десятичное число от 0 до 1 с 16 цифрами после запятой после запятой (например, 0.4363923368509859
).0.6fb7687f
). Math.random().toString(16)
.0.6fb7687f
префикс 0.
(0.6fb7687f
=> 6fb7687f
) и получаем строку длиной восемь шестнадцатеричных символов. (Math.random().toString(16).substr(2,8)
.Math.random()
возвращает более короткое число (например, 0.4363
) из-за нулей в конце (из приведенного выше примера на самом деле это значение равно 0.4363000000000000
). Вот почему я добавляю к этой строке "000000000"
(строку с девятью нулями), а затем обрезаю ее с помощью функции substr()
чтобы сделать ее точно равной девяти символам (заполняя нули справа).Math.random()
будет возвращать ровно 0 или 1 (вероятность Math.random()
^ 16 для каждого из них). Поэтому нам нужно было добавить к нему девять нулей ("0"+"000000000"
или "1"+"000000000"
), а затем отрезать его от второго индекса (3-го символа) длиной восемь символов. В остальных случаях добавление нулей не повредит результату, так как он все равно обрезает его. Math.random().toString(16)+"000000000").substr(2,8)
.Ассамблея:
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
.XXXXXXXX
и -XXXX-XXXX
.-XXXX-XXXX
ниже: XXXXXXXX
-XXXX-XXXX
-XXXX-XXXX
XXXXXXXX
._p8(s)
пар _p8(s)
, s
параметр s
сообщает функции, добавлять ли тире или нет._p8() + _p8(true) + _p8(true) + _p8()
и возвращаем его.Ссылка на этот пост в моем блоге
Наслаждайтесь! :-)
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>
Если идентификатор генерируется с интервалом более 1 миллисекунды, он уникален на 100%.
Если два идентификатора генерируются с более короткими интервалами и при условии, что случайный метод является действительно случайным, это приведет к созданию идентификатора, который с вероятностью 99,9999999999999% будет глобально уникальным (коллизия в 1 из 10 ^ 15)
Вы можете увеличить это число, добавив больше цифр, но для создания 100% уникального идентификатора вам нужно будет использовать глобальный счетчик.
если вам действительно нужно соответствие RFC, это форматирование будет считаться действительным GUID версии 4:
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>
Изменение: приведенный выше код следуют намерению, но не букве RFC. Среди других расхождений это несколько случайных цифр. (Добавьте больше случайных цифр, если вам это нужно). Плюс в том, что это действительно быстро, по сравнению со 100% совместимым кодом. Вы можете проверить свой GUID здесь
Вот комбинация верхнего голосуемого ответа с обходным решением для столкновений Chrome:
generateGUID = (typeof(window.crypto) != 'undefined' &&
typeof(window.crypto.getRandomValues) != 'undefined') ?
function() {
// If we have a cryptographically secure PRNG, use that
// /questions/1755/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);
});
};
На jsbin, если вы хотите проверить его.
, does not keep the Version 4 UUIDs format defined by RFC 4122. That is instead of
xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx` она выдает xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
.
Вот полностью несовместимая, но очень эффективная реализация для создания уникального идентификатора с идентификатором GUID, совместимого с ASCII.
function generateQuickGuid() {
return Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
}
Генерирует 26 [a-z0-9] символов, что дает UID, который является более коротким и уникальным, чем GUID, совместимый с RFC. Тишины могут быть добавлены тривиально, если важна удобочитаемость человека.
Вот примеры использования и тайминги для этой функции, а некоторые из них - другие ответы. Сроки выполнялись в Chrome m25, по 10 миллионов итераций каждый.
>>> 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
Вот код синхронизации.
var r;
console.time('t');
for (var i = 0; i < 10000000; i++) {
r = FuncToTest();
};
console.timeEnd('t');
Здесь решение от 9 октября 2011 г. из комментария пользователя 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)}
Это достигает той же цели, что и текущий ответ с наивысшим рейтингом, но в 50+ меньше байтов, используя принуждение, рекурсию и экспоненциальную нотацию. Для тех, кому интересно, как это работает, здесь представлена аннотированная форма более старой версии функции:
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
)
}
export const UUID = function b (a: number): string { return a ? (a^Math.random()*16>>a/4).toString(16) : (''+[1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, b) };
Вы можете использовать node-uuid (https://github.com/kelektiv/node-uuid)
Простое, быстрое поколение RFC4122 UUIDS.
Особенности:
Установить с помощью NPM:
npm install uuid
Или используя uuid через браузер:
Загрузить файл Raw (uuid v1): https://raw.githubusercontent.com/kelektiv/node-uuid/master/v1.js Загрузить файл Raw (uuid v4): https://raw.githubusercontent.com/kelektiv/node -uuid/мастер/v4.js
Хотите еще меньше? Проверьте это: https://gist.github.com/jed/982883
Использование:
// 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();
Из технического журнала 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;
}
Существуют и другие методы, которые включают использование элемента управления ActiveX, но держитесь подальше от них!
Edit: Я думал, что стоит отметить, что никакой GUID-генератор не может гарантировать уникальные ключи (проверьте статью в Википедии). Всегда есть вероятность столкновения. GUID просто предлагает достаточно большой набор ключей для уменьшения смены столкновений почти до нуля.
Полезен веб-сервис.
Быстрый поиск Google: http://www.hoskinson.net/GuidGenerator/
Нельзя ручаться за эту реализацию, но кто-то должен опубликовать генератор GUID bonafide.
С таким веб-сервисом вы можете разработать веб-интерфейс REST, который использует веб-службу GUID, и служит через AJAX для javascript в браузере.
Простой модуль JavaScript как комбинация лучших ответов в этом потоке.
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());
Использование:
Guid.newGuid()
"c6c2d12f-d76b-5739-e551-07e6de5b0807"
Guid.empty
"00000000-0000-0000-0000-000000000000"
GUID
в виде string
. Ваш ответ, по крайней мере, касается гораздо более эффективного хранилища с использованием Uint16Array
. Функция toString
должна использовать двоичное представление в object
JavaScript
_cryptoGuid
не _cryptoGuid
включать '4' в начале 3-го раздела, как _guid
?
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:
Пересмотрен мой проект, который использовал эту функцию и не любил многословие. - Но нужна правильная случайность.
Версия, основанная на ответе Briguy37, и некоторые побитовые операторы, чтобы извлечь из буфера окна размером с размеру.
Следует придерживаться схемы RFC Type 4 (random), так как у меня были проблемы с последним анализом проблем с uuids с Java UUID.
Из good ol 'wikipedia есть ссылка на реализацию UUID javascript.
Он выглядит довольно элегантно и, возможно, может быть улучшен путем соления с хешем IP-адреса клиента. Этот хэш, возможно, может быть вставлен в сервер html-документа для использования на стороне клиента javascript.
ОБНОВЛЕНИЕ: Исходный сайт имел перетасовку, вот обновленная версия
Ну, у этого уже есть куча ответов, но, к сожалению, в связке нет "истинного" случайного. Нижеприведенная версия является адаптацией ответа broofa, но обновлена, чтобы включить "истинную" случайную функцию, которая использует доступные криптографические библиотеки, и функцию Alea() в качестве резервной копии.
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);
});
};
rval = rval & mask
так как она rval = rval & mask
результат до 32 бит. Операции с битами - только 32 бита в JS. Более того, если вы применяете его только в конце, тогда 3 младших бита уже потеряны при генерировании 53-битного значения, поскольку первый цикл создает 56-битное значение (255 * 2 ^ 48). Вместо этого вам нужно использовать этот код: `var byte = byteArray [i]; if (p + 8> bits_needed) byte & = (255 >> p + 8 - bits_needed); rval + = byte * Math.pow (2, p); `Вы можете посмотреть тест здесь: jsfiddle.net/xto6969y/1
Проект JavaScript на GitHub - https://github.com/LiosK/UUID.js
UUID.js Генератор UUID, совместимый с RFC для JavaScript.
См. RFC 4122 http://www.ietf.org/rfc/rfc4122.txt.
Возможности Создает совместимые с RFC 4122 UUID.
Версии 4 UUID (UUID от случайных чисел) и UUID версии 1 (временные UUID).
Объект UUID допускает разнообразный доступ к UUID, включая доступ к поля UUID.
Низкое временное разрешение JavaScript компенсируется случайным числа.
Это создаст UUID версии 4 (созданный из псевдослучайных чисел):
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('');
}
Вот пример сгенерированных UUID:
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('-');
Настроил мой собственный генератор UUID/GUID с некоторыми дополнительными функциями здесь.
Я использую следующий генератор случайных чисел Kybos, чтобы немного криптографически звучать.
Ниже приведен мой script с помощью методов Mash и Kybos, исключенных из baagoe.com.
//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));
Я хотел понять ответ broofa, поэтому я расширил его и добавил комментарии:
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);
}
);
};
Лучший способ:
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
}
Минимизация:
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}
Для тех, кто хочет получить совместимое с rfc4122 решение 4 с учетом скорости (несколько вызовов в 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("");
}
Вышеуказанная функция должна иметь приличный баланс между скоростью и случайностью.
Это просто простой вызов AJAX...
Если кому-то все еще интересно, вот мое решение.
На стороне сервера:
[WebMethod()]
public static string GenerateGuid()
{
return Guid.NewGuid().ToString();
}
На стороне клиента:
var myNewGuid = null;
PageMethods.GenerateGuid(
function(result, userContext, methodName)
{
myNewGuid = result;
},
function()
{
alert("WebService call failed.");
}
);
Пример ES6
const guid=()=> {
const s4=()=> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4() + s4() + s4()}`;
}
Я знаю, это старый вопрос. Для полноты, если ваша среда - SharePoint, есть функция утилиты, называемая SP.Guid.newGuid
(msdn link), которая создает новый guid. Эта функция находится внутри файла sp.init.js. Если вы перепишите эту функцию (чтобы удалить некоторые другие зависимости от других частных функций), она выглядит так:
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;
};
Существует плагин jQuery, который обрабатывает Guid nicely @http://plugins.jquery.com/project/GUID_Helper
jQuery.Guid.Value()
Возвращает значение внутреннего Guid. Если указатель не указан, возвращается новый (значение затем сохраняется внутри).
jQuery.Guid.New()
Возвращает новое руководство и устанавливает его значение внутри.
jQuery.Guid.Empty()
Возвращает пустой Guid 00000000-0000-0000-0000-000000000000.
jQuery.Guid.IsEmpty()
Возвращает логическое значение. True, если пусто / undefined/blank/null.
jQuery.Guid.IsValid()
Возвращает логическое значение. True valid guid, false, если нет.
jQuery.Guid.Set()
Регламент. Устанавливает Guid для указанного пользователем Guid, если недействительно, возвращает пустой указатель.
Это основано на дате и добавляет случайный суффикс для "обеспечения" уникальности. Хорошо работает для идентификаторов css. Он всегда возвращает что-то вроде и легко взломать:
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;
};
Странно, что никто еще не упомянул об этом, но для полноты, существует множество генераторов guid на npm. Я готов поспорить, что большинство из них работают в браузере тоже.
Если вам просто нужна случайная 128-битная строка в каком-либо конкретном формате, вы можете использовать:
function uuid() {
return crypto.getRandomValues(new Uint32Array(4)).join('-');
}
Что вернет что-то вроде 2350143528-4164020887-938913176-2513998651
.
Еще один более читаемый вариант с двумя мутациями.
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, '-');
}
Важно, чтобы использовать хорошо протестированный код, который поддерживается более чем одним участником, вместо того, чтобы бить ваши собственные вещи для этого. Это одно из мест, где вы, вероятно, предпочитаете наиболее стабильный код, чем кратчайшая возможная умная версия, работающая в X-браузере, но не учитывающая особенности Y, которые часто приводят к очень сложному исследованию ошибок, чем проявляются только случайным образом для некоторых пользователей. Лично я использую uuid-js в https://github.com/aurigadl/uuid-js, с помощью которого активирована поддержка, чтобы я мог легко получать обновления.
Простой код, который использует crypto.getRandomValues(a)
в поддерживаемые браузеры (IE11 +, iOS7 +, FF21 +, Chrome, Android Chrome). Избегает использования Math.random()
, потому что это может вызвать коллизии (например, 20 столкновений для 4000 сгенерированных uuids в реальной ситуации 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);
}
Примечания:
x
и общие идентификаторы сжимаются очень хорошо) , - Робокат 8 минут назад
Я нашел этот script полезным для создания GUID в JavaScript
https://github.com/addui/GUIDJS
var myGuid = GUID();
На всякий случай, если кто-либо заходит по Google, ищет небольшую библиотеку-утилиту, ShortId (https://www.npmjs.com/package/shortid) отвечает всем требованиям этого вопроса. Он позволяет указать допустимые символы и длину и гарантирует последовательность, не повторяющуюся, не повторяющуюся.
Чтобы сделать это более реальным ответом, ядро этой библиотеки использует следующую логику для создания своих коротких идентификаторов:
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;
}
Я не редактировал это, чтобы отражать только самые основные части этого подхода, поэтому приведенный выше код содержит некоторую дополнительную логику из библиотеки. Если вам интересно все, что он делает, посмотрите на источник: https://github.com/dylang/shortid/tree/master/lib
Вы можете использовать npm package guid, генератор направляющих и валидатор.
https://www.npmjs.com/package/guid
Пример:
Guid.raw();
// -> '6fdf6ffc-ed77-94fa-407e-a7b86ed9e59d'
UPDATE: этот пакет устарел. Вместо этого используйте uuid.
https://www.npmjs.com/package/uuid
Пример:
const uuidv4 = require('uuid/v4');
uuidv4(); // ⇨ '10ba038e-48da-487b-96e8-8d3b99b6d18a'
Я использую эту функцию ниже, надеюсь, что это может быть полезно.
function NewGuid()
{
var sGuid="";
for (var i=0; i<32; i++)
{
sGuid+=Math.floor(Math.random()*0xF).toString(0xF);
}
return sGuid;
}
0xF
вместо 15
?
Привет, вот рабочий пример, он генерирует 32-значный уникальный UUID.
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)
Для моего случая использования мне потребовалось создание поколения, которое гарантировалось бы уникальным в глобальном масштабе; без исключений. Некоторое время я боролся с проблемой и придумал решение под названием tuid (Truly Unique ID). Он генерирует идентификатор с первыми 32 символами, сгенерированными системой, и оставшиеся цифры, представляющие миллисекунды с эпохи. В ситуациях, когда мне нужно генерировать id на клиентском javascript, он работает хорошо. Посмотрите:
основанный на работе broofa, я добавил еще несколько случайностей, добавив метку времени в math.random()
Надеюсь, это может помочь
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);
});
}
Для тех, кто использует Javascript в Windows (например, WScript/CScript/MSHTA). Можно использовать ActiveX
. В частности, объект Scriptlet.Typelib
:
WScript.Echo((new ActiveXObject("Scriptlet.TypeLib")).Guid)
Обратите внимание, что этот ответ работает только на тех технологиях, которые я перечисл, он не будет работать ни в одном браузере, даже в Microsoft Edge! Таким образом, ваш пробег будет отличаться от этого ответа.
Здесь вы можете найти очень маленькую функцию, которая генерирует uuids https://gist.github.com/jed/982883
Одна из окончательных версий:
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
)
}
ОК, используя пакет uuid, он поддерживает UUID версий 1, 3, 4 и 5:
yarn add uuid
а потом:
const uuidv1 = require('uuid/v1');
uuidv1(); // ⇨ '45745c60-7b1a-11e8-9c9c-2d42b21b1a3e'
Вы также можете сделать это с помощью полностью определенных опций:
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'
Для получения дополнительной информации посетите страницу npm здесь
Я не смог найти ответа, который бы использовал один 16- TypedArray
и DataView
, поэтому я думаю, что следующее решение для генерации UUID версии 4 для RFC будет стоять здесь самостоятельно:
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
}
Я предпочитаю это, потому что он опирается только на функции, доступные для стандартной платформы ECMAScript.
Для науки. Я еще не видел, чтобы кто-то это делал... это не совместимо с v4, но его можно было легко изменить. Это просто пример расширения типа Uint8Array и использование crypto.getRandomValues() для генерации значений байтов 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
}
}
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);
}
Это может быть полезно кому-то...
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++;
};
Просто подумал, что я отправлю еще один способ сделать то же самое.
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;
}
Простое решение для генерации уникальной идентификации - использовать токен времени и добавить к нему случайное число. Я предпочитаю префикс "uuid-".
Ниже функция генерирует случайную строку типа: uuid-14d93eb1b9b4533e6. Не нужно генерировать 32 символа случайной строки. 16 char случайная строка более чем достаточна в этом случае, чтобы предоставить уникальные UUID в javascript.
var createUUID = function() { return"uuid-"+((new Date).getTime().toString(16)+Math.floor(1E7*Math.random()).toString(16)); }
Я получаю, что это старый вопрос, но я узнал что-то новое несколько дней назад, и я думаю, это хорошее место, чтобы "разделить" его:
Используя Change.js, вы получаете уникальный GUID с одной строкой кода:
var chance = new Chance();
document.body.innerHTML = chance.guid();
body { font-family: Tahoma }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Chance.js</title>
</head>
<body>
<script src="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
<link href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css" rel="stylesheet" type="text/css" />
<script src="http://chancejs.com/chance.min.js"></script>
</body>
</html>
Тот, который я использовал в последнее время:
const uuid = function b(a) {
return a ? (a ^ Math.random() * 16 >> a / 4).toString(16) :
([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, b);
};
у него есть зависимость от mongodb, конечно, но у меня лично это где-то вокруг в любом случае, поэтому генерация нового идентификатора проста:
const ObjectID = require('mongodb').ObjectID;
let id = new ObjectID().toString();
Я знаю, что эта тема старая, но если вы действительно хотели создать GUID, вы могли бы obvioulsy сделать это без прямого javascript. Вы можете привести к истечению срока действия каждой загрузки и создать GUID на стороне сервера, а затем заполнить ее в переменной javascript во время выполнения страницы. Просто идея.