it-swarm.com.ru

Создайте GUID / UUID в JavaScript?

Я пытаюсь создать глобально уникальные идентификаторы в JavaScript. Я не уверен, какие подпрограммы доступны во всех браузерах, насколько «случайным» и затравленным является встроенный генератор случайных чисел и т.д.

GUID/UUID должен содержать не менее 32 символов и должен оставаться в диапазоне ASCII, чтобы избежать проблем при их передаче.

3519
Jason Cohen

UUID (универсальный уникальный идентификатор), также известный как GUID (глобальный уникальный идентификатор), согласно RFC 4122 , являются идентификаторами с определенной гарантией уникальности.

Лучший способ их генерирования - следовать инструкциям по реализации в указанном RFC, использовать одну из многих проверенных реализаций с открытым исходным кодом или использовать встроенную реализацию для языков, в которых она есть.

Некоторые примеры инструментов с открытым исходным кодом для работы с UUID, для некоторых популярных языков программирования перечислены здесь.

JavaScript

PHP

Идти

Рубин

Python

  • В модуле UUID

Обратите внимание, что просто случайная генерация идентификаторов побайтово или посимвольно не даст вам таких же гарантий, как соответствующая реализация. Кроме того, очень важно, что системы, работающие с совместимыми UUID, могут не принимать случайно сгенерированные, и многие валидаторы с открытым исходным кодом на самом деле проверяют правильность структуры.

UUID должен иметь этот формат:

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

Где позиции M и N могут иметь только определенные значения. В настоящее время единственными допустимыми значениями для M являются 1, 2, 3, 4 и 5, поэтому случайная генерация этой позиции сделает большинство результатов неприемлемыми.

2098
John Millikin

Для 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())

Update, 2015-06-02: Учтите, что уникальность UUID в значительной степени зависит от базового генератора случайных чисел (RNG). В приведенном выше решении для краткости используется Math.random(), однако Math.random()не гарантированно является высококачественным ГСЧ. См. Адама Хайленда отличная рецензия на Math.random () для подробностей. Для более надежного решения рассмотрите что-то вроде модуль uuid [Отказ от ответственности: я автор], который использует API RNG более высокого качества, где это возможно.

Update, 2015-08-26: В качестве дополнительного примечания в этом Gist описывается, как определить, сколько идентификаторов может быть сгенерировано до достижения определенной вероятности столкновения. Например, с 3.26x1015 версия 4 RFC4122 UUID у вас есть шанс столкновения 1 на миллион.

Update, 2017-06-28: A хорошая статья от разработчиков Chrome обсуждается состояние качества Math.random PRNG в Chrome, Firefox и Safari. tl; dr - По состоянию на конец 2015 года это "довольно хорошо", но не криптографическое качество. Чтобы решить эту проблему, вот обновленная версия вышеупомянутого решения, которая использует ES6, API crypto и немного волшебства JS, за которое я не могу поверить :

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

3399
broofa

Мне действительно нравится, насколько чистым ответ Бруфы является, но, к сожалению, плохие реализации 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);
    });
}


Вот скрипка для проверки.

726
Briguy37

ответ broofa довольно приятный, действительно - впечатляюще умный, действительно ... rfc4122-совместимый, несколько читабельный и компактный. Потрясающие!

Но если вы посмотрите на это регулярное выражение, эти многочисленные вызовы функций replace(), toString() и Math.random() (где он использует только 4 бита результата и тратит впустую все остальное), вы можете начать задумываться о производительности. Действительно, joelpt даже решил отказаться от RFC для общей скорости GUID с generateQuickGUID.

Но можем ли мы получить скорость и соответствие RFC? Я говорю ДА! Можем ли мы поддерживать читабельность? Ну ... Не совсем, но это легко, если вы будете следовать.

Но сначала, мои результаты, по сравнению с brooa, 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.

Таким образом, благодаря шестой итерации оптимизаций я побил самый популярный ответ более чем на 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, в то время как broofa этого не делали. Кроме того, обратите внимание, что мы можем использовать индексирование 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()) дает нам почти трехкратное улучшение!

Следующим шагом будет небольшой шаг на рабочем столе, но он будет иметь большое значение для мобильных устройств. Давайте сделаем меньше вызовов 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.

353
Jeff Ward

Вот некоторый код, основанный на 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;
}
142
Kevin Hakanson

Самый быстрый 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 цифрами после запятой (для Example 0.4363923368509859).
  • Затем мы берем это число и конвертируем it в строку с основанием 16 (из приведенного выше примера мы получим 0.6fb7687f).
    Math.random().toString(16).
  • Затем мы обрезаем префикс 0. (0.6fb7687f => 6fb7687f) и получаем строку длиной восемь шестнадцатеричных символов
    (Math.random().toString(16).substr(2,8).
  • Иногда функция Math.random() будет возвращать Более короткое число (например, 0.4363) из-за нулей в конце (из приведенного выше примера на самом деле это 0.4363000000000000). Вот почему я добавляю к этой строке "000000000" (строку с девятью нулями), а затем обрезаю ее функцией substr(), чтобы сделать ее ровно девятью символами (заполняя нули справа).
  • Причиной добавления ровно девяти нулей является сценарий наихудшего случая, когда функция Math.random() будет возвращать ровно 0 или 1 (вероятность 1/10 ^ 16 для каждого из них). Вот почему нам нужно было добавить к нему девять нулей ("0"+"000000000" или "1"+"000000000"), а затем вырезать его из второго индекса (3-й символ) длиной восемь символов. В остальных случаях добавление нулей не повредит результату, так как он все равно обрезает его.
    Math.random().toString(16)+"000000000").substr(2,8).

Ассамблея:

  • GUID имеет следующий формат XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.
  • Я разделил GUID на 4 части, каждая из которых разделена на 2 типа (или формата): XXXXXXXX и -XXXX-XXXX.
  • Теперь я собираю GUID, используя эти два типа для сборки GUID с помощью вызова из 4 частей, как показано ниже: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.
  • Чтобы различать эти два типа, я добавил параметр flag в функцию создания пары _p8(s), параметр s сообщает функции, добавлять ли тире или нет.
  • В конце концов мы создаем GUID со следующей цепочкой: _p8() + _p8(true) + _p8(true) + _p8() и возвращаем его.

Ссылка на этот пост в моем блоге

Наслаждаться! :-)

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

Если идентификаторы генерируются с интервалом более 1 миллисекунды, они уникальны на 100%.

Если два идентификатора генерируются с более короткими интервалами и при условии, что случайный метод является действительно случайным, это приведет к созданию идентификаторов, которые с вероятностью 99,999999999999999% будут глобально уникальными (столкновение в 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 здесь

81
Simon Rigét

Вот комбинация ответа с наибольшим количеством голосов , с обходным путем для столкновений 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);
        });
    };

На jsbin , если вы хотите проверить это.

60
ripper234

Вот решение от 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
      )
}
55
Jed Schmidt

Вот совершенно несовместимая, но очень производительная реализация для генерации ASCII-безопасного GUID-подобного уникального идентификатора.

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

Генерирует 26 [a-z0-9] символов, что дает UID, который является более коротким и более уникальным, чем RFID-совместимые GUID. Тире могут быть тривиально добавлены, если удобочитаемость имеет значение.

Вот примеры использования и время для этой функции и несколько других ответов на этот вопрос. Синхронизация была выполнена под 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');
54
joelpt

Вы можете использовать node-uuid ( https://github.com/kelektiv/node-uuid )

Простое, быстрое поколение RFC4122 UUIDS.

Особенности:

  • Сгенерируйте UUID RFC4122 версии 1 или версии 4
  • Запускается в node.js и браузерах.
  • Криптографически сильная генерация случайных чисел на поддерживающих платформах.
  • Маленький след (Хотите что-то поменьше? Проверьте это! )

Установить с помощью 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/master/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();
32
Kyros Koh

От технический блог Саги Шкеди :

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 просто предлагает достаточно большую совокупность ключей, чтобы уменьшить количество столкновений почти до нуля.

31
Prestaul

Веб-сервис будет полезен. 

Быстрый Google нашел: http://www.hoskinson.net/GuidGenerator/

Не могу поручиться за эту реализацию, но SOMEONE должен опубликовать добросовестный генератор GUID.

С помощью такого веб-сервиса вы могли бы разработать веб-интерфейс REST, который использует веб-сервис GUID и передает его через AJAX для javascript в браузере.

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

Правка:

Пересмотрел мой проект, который использовал эту функцию и не понравился многословие. - Но нужна была правильная случайность.

Версия, основанная на ответе Briguy37 и некоторых побитовых операторах для извлечения окон размером с полубайт из буфера.

Следует придерживаться схемы RFC Type 4 (случайная), так как в прошлый раз у меня были проблемы с анализом несовместимых uuids с UUID в Java.

29
sleeplessnerd

Простой модуль 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"

28
kayz1

Из доброй старой википедии есть ссылка на реализацию UUID на javascript.

Это выглядит довольно элегантно, и, возможно, его можно улучшить, добавив хеш IP-адреса клиента. Возможно, этот хеш может быть вставлен в html-документ на стороне сервера для использования клиентским javascript.

ОБНОВЛЕНИЕ: оригинальный сайт был случайным образом, вот обновленная версия

23
Dan

Ну, на это уже есть куча ответов, но, к сожалению, в этой группе нет «настоящего» случайного числа. Приведенная ниже версия является адаптацией ответа 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);
  });
};
23
jvenema

Проект JavaScript на GitHub - https://github.com/LiosK/UUID.js

UUID.js RFC-совместимый генератор UUID для JavaScript.

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

Особенности Создает UUID, соответствующие RFC 4122.

UUID версии 4 (UUID из случайных чисел) и UUID версии 1 (основанные на времени UUID) доступны.

Объект UUID обеспечивает различные возможности доступа к UUID, включая доступ к поля UUID.

Низкое временное разрешение JavaScript компенсируется случайным образом номера.

21
Wojciech Bednarski

Это создает 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
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

Скорректировал мой собственный генератор UUID/GUID с некоторыми дополнениями здесь .

Я использую следующий Kybos генератор случайных чисел, чтобы быть немного более криптографически обоснованным.

Ниже приведен мой скрипт с исключенными методами 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));
13
Tracker1

Лучший способ:

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

Я хотел понять ответ брофы, поэтому я расширил его и добавил комментарии:

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

Образец 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

Это просто 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.");
    }
);
11
alekop

Для тех, кто хочет 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("");
}

Вышеуказанная функция должна иметь приличный баланс между скоростью и случайностью.

11
John Fowler

Есть плагин jQuery, который прекрасно обрабатывает Guid @ http://plugins.jquery.com/project/GUID_Helper

jQuery.Guid.Value()

Возвращает значение внутреннего Guid. Если guid не был указан, возвращает новый (значение затем сохраняется внутри).


jQuery.Guid.New()

Возвращает новый Guid и устанавливает его значение внутренне.


jQuery.Guid.Empty()

Возвращает пустой Guid 00000000-0000-0000-0000-000000000000.


jQuery.Guid.IsEmpty()

Возвращает логическое значение. Истинно, если пусто/неопределено/пусто/пусто.


jQuery.Guid.IsValid()

Возвращает логическое значение. Истинный действительный гид, ложный, если нет.


jQuery.Guid.Set()

Retrns Guid. Устанавливает Guid для указанного пользователем Guid, если недействительный, возвращает пустой guid.

10
Levitikon

Я знаю, это старый вопрос. Просто для полноты, если ваша среда - 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;
};
10
Anatoly Mironov

Этот основан на дате и добавляет случайный суффикс для «обеспечения» уникальности . Хорошо работает для идентификаторов 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;
        };
9
ling

Простой код, который использует 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);
}

Заметки:

  • Оптимизирован для удобства чтения кода, а не для скорости, поэтому подходит, например, для нескольких сотен единиц в секунду. Генерирует около 10000 uuid () в секунду в Chromium на моем ноутбуке, используя http://jsbin.com/fuwigo/1 для измерения производительности.
  • Использует только 8 для «y», потому что это упрощает читабельность кода (y может быть 8, 9, A или B).
6
robocat

Если вам просто нужна случайная 128-битная строка без определенного формата, вы можете использовать:

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

Который будет возвращать что-то вроде 2350143528-4164020887-938913176-2513998651.

6
Jonathan Potter

Важно использовать хорошо протестированный код, который поддерживается более чем 1 участником, вместо того, чтобы использовать для этого свой собственный материал. Это одно из тех мест, где вы, вероятно, хотите отдать предпочтение наиболее стабильному коду, а не самой короткой из возможных умных версий, которые работают в браузере X, но не учитывают особенности Y, которые часто приводят к очень трудным исследованиям ошибок, а не случайным образом. для некоторых пользователей. Лично я использую uuid-js по адресу https://github.com/aurigadl/uuid-js , в котором включена беседка, чтобы я мог легко получать обновления.

5
Shital Shah

Просто еще один более читаемый вариант с двумя мутациями.

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

Я использую эту функцию ниже, надеюсь, это может быть полезно.

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

Вы можете использовать пакет npm guid, генератор 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'
3
andersh

На тот случай, если кто-нибудь, заскочивший через 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;
}

Я не редактировал это, чтобы отразить only самые основные части этого подхода, поэтому приведенный выше код включает некоторую дополнительную логику из библиотеки. Если вам интересно обо всем, что он делает, посмотрите на источник: https://github.com/dylang/shortid/tree/master/lib

3
MaxPRafferty

Я нашел этот скрипт полезным для создания GUID в JavaScript

https://github.com/addui/GUIDJS

var myGuid = GUID();
3
Dustin Poissant

Для тех, кто использует Javascript в Windows (например, WScript/CScript/MSHTA). Можно использовать ActiveX. В частности, объект Scriptlet.Typelib:

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

Обратите внимание, что этот ответ работает только с технологиями, которые я перечислил, он не будет работать ни с одним браузером, даже с Microsoft Edge! Таким образом, ваш пробег будет зависеть от этого ответа.

2
Stephen Quan

Для моего варианта использования мне потребовалось генерирование идентификатора, который гарантированно был уникальным во всем мире; без исключений. Некоторое время я боролся с этой проблемой и придумал решение под названием tuid (действительно уникальный идентификатор). Он генерирует идентификатор, причем первые 32 символа генерируются системой, а оставшиеся цифры представляют миллисекунды с начала эпохи. В ситуациях, когда мне нужно генерировать идентификаторы на клиентском JavaScript, это работает хорошо. Посмотри:

https://github.com/mongoh/tuid

2
Rishi

Привет, вот рабочий пример, он генерирует 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)
2
Ashish Yadav

Я не смог найти ответа, который использовал бы один 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.

1
amn

основанный на работе brooa, я добавил немного случайности, добавив метку времени в 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);
    });
}
1
freecloud

Здесь вы можете найти очень маленькую функцию, которая генерирует 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
      )
}
1
Pablo Pazos

Простым решением для генерации уникальной идентификации является использование токена времени и добавление к нему случайного числа. Я предпочитаю использовать префикс "uuid-".

Функция ниже создаст случайную строку типа: uuid-14d93eb1b9b4533e6 . Не нужно генерировать 32 символа случайной строки. В этом случае более 16 символов случайной строки более чем достаточно для предоставления уникальных UUID в javascript.

 var createUUID = function () {
 return "uuid -" + ((новая дата) .getTime (). toString (16) + Math.floor (1E7 * Math.random ()). toString (16)); 
} 
0
mangalbhaskar

Хорошо, используя пакет uuid, он поддерживает version 1, 3, 4 и 5 UUIDs:

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 здесь

0
Alireza

Просто подумал, что опубликую еще один способ сделать то же самое.

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

Это может быть полезно кому-то ...

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

Мы можем использовать replace и crypto.getRandomValues, чтобы получить такой вывод:

xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx

 enter image description here

Если мы ищем оптимальное решение, мы должны заменить crypto.getRandomValues(new Uint8Array(1))[0] на массив (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());

Чтобы получить этот код:

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

Столкновение:

Мы можем сделать как Google Analytics и добавить метку времени с: uuidv4() + "." + (+new Date()).

0
A-312

Для науки. Я еще не видел, чтобы кто-то делал это ... он не соответствует 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
        }
    }
0
Jacob Ochoa