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

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

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

30 ответов


было несколько попыток сделать это. Вопрос в том, хотите ли вы фактические GUID или просто случайные числа, которые посмотреть как GUIDs? Достаточно легко генерировать случайные числа.

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

однако обратите внимание, что такие значения не являются подлинными GUIDs.

Примечание: предоставленный фрагмент кода не следует RFC4122, который требует, чтобы версия (4) должен быть интегрирован в сгенерированную выходную строку. не используйте этот ответ если вам нужны совместимые GUID.

использование:

var uuid = guid();

демо:

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

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

document.getElementById('jsGenId').addEventListener('click', function() {
  document.getElementById('jsIdResult').value = guid();
})
input { font-family: monospace; }
<button id="jsGenId" type="button">Generate GUID</button>
<br>
<input id="jsIdResult" type="text" placeholder="Results will be placed here..." readonly size="40"/>

на 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() и не гарантированно высокое качество ГСЧ. См. Адама Хайланда отличные сочинение по математике.random () для сведения. Для более надежного решения рассмотрим что-то вроде модуль uuid[отказ от ответственности: я автор], который использует API RNG более высокого качества, где это возможно.

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

обновление, 2017-06-28: A хорошая статья от разработчиков Chrome обсуждение состояния математики.случайное качество PRNG в Chrome, Firefox и Safari. tl; dr-по состоянию на конец 2015 года это "довольно хорошее", но не криптографическое качество. Чтобы решить эту проблему, вот обновленная версия вышеуказанного решения, которое использует ES6,crypto API, и немного 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());

мне очень нравится, как чистый!-ОтветBroofa это!--5-- > есть, но жаль, что плохие реализации 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);
    });
}


вот скрипка, чтобы проверить.


broofa-это красиво, действительно - впечатляюще умная, правда... 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-й итерации оптимизаций я избил самый популярный ответ по over 12X, принятый ответ конец 9X, и быстрый-несоответствующий ответ 2-3X. И я все еще rfc4122 совместимый.

интересно как? Я поставил полный источник наhttp://jsfiddle.net/jcward/7hyaC/3/ и далее http://jsperf.com/uuid-generator-opt/4

для объяснения, давайте начнем с кода broofa это:

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

таким образом, он заменяет x С любой случайной шестнадцатеричной цифрой,y со случайными данными (кроме принуждение верхних 2 бит к 10 в спецификации RFC), и регулярное выражение не соответствует - или 4 персонажи, поэтому ему не нужно иметь с ними дело. Очень, очень ловко.

первое, что нужно знать, это то, что вызовы функций дороги, как и регулярные выражения (хотя он использует только 1, он имеет 32 обратных вызова, по одному для каждого матча, и в каждом из 32 обратных вызовов он вызывает математику.random() и v. toString (16)).

первый шаг к производительности регулярное выражение и его функции обратного вызова и вместо этого используют простой цикл. Это означает, что мы должны иметь дело с - и 4 символы, в то время как broofa не. Кроме того, обратите внимание, что мы можем использовать индексацию массива строк, чтобы сохранить его гладкую архитектуру шаблона строки:

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-кратное улучшение!

следующий шаг маленький на рабочем столе, но делает приличную разницу на мобильный телефон. Давайте сделаем меньше математики.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 бит за раз, все еще используя 256-элементный LUT, и он показал уменьшающиеся результаты оптимизации. Хотя он имел меньше итераций, внутренняя логика была осложнена увеличенной обработкой, и она выполняла то же самое на рабочем столе и только ~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];
}

Modualized:http://jcward.com/UUID.js -UUID.generate()

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

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

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


вот некоторый код, основанный на 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).
  • Затем берем это число и преобразуем это строка с базой 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() функция для того чтобы сделать им 9 характеров точно (заполняя нули к право.)
  • причина добавления ровно девяти нулей заключается в худшем сценарии, когда 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, используя эти 2 типа для сборки GUID с вызовом 4 штук, следующим образом:XXXXXXXX -XXXX-XXXX -XXXX-XXXX XXXXXXXX.
  • чтобы отличаться между этими двумя типами, I добавлен параметр flag в функцию pair creator _p8(s), the s параметр указывает функции, следует ли добавлять тире или нет.
  • в конце концов мы создаем GUID со следующей цепочкой:_p8() + _p8(true) + _p8(true) + _p8(), и вернуть его.

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

наслаждайтесь! :-)


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

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

Если два идентификатора генерируются с более короткими интервалами и предполагают, что случайный метод действительно случайный, это будет генерировать идентификаторы, которые 99.99999999999999%, вероятно, будут глобально уникальными (столкновение в 1 из 10^15)

вы можете увеличить это число, добавив больше цифр, но для создания 100% уникальных идентификаторов вам нужно будет использовать глобальный счетчик.

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

вот комбинация топ-проголосовали ответ, С решения Столкновения 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 Если вы хотите, чтобы проверить его.


вот решение, датированное октябрем. 9, 2011 из комментария пользователя Джед at 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
      )
}

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

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

генерирует 26 [a-z0-9] символов, давая UID, который является более коротким и уникальным, чем RFC совместимые 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');

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

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 в браузере.


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 и некоторых побитовых операторах для извлечения окон размера nibble из буфера.

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


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

"00000000-0000-0000-0000-000000000000"


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

простое, быстрое поколение RFC4122 идентификаторы UUID.

характеристики:

  • генерация RFC4122 версии 1 или версии 4 UUIDs
  • работает в узле.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'

ЕС6:

import uuid from 'uuid/v4';
const id = uuid();

с хороший ol' Википедии есть ссылка на реализацию UUID на javascript.

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

UPDATE: исходный сайт имел перетасовку, вот обновленная версия


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

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

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

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

Features генерирует совместимые UUID RFC 4122.

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

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

вот образец генерируемых UUIDs:

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

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

лучше:

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}

Я хотел понять ответ 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);
        }
    );
};

это просто простой вызов 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.");
    }
);

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

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


Я знаю, это старый вопрос. Просто для полноты, если ваша среда SharePoint, есть функция утилиты под названием SP.Guid.newGuid (msdn link), который создает новый идентификатор guid. Эта функция находится внутри sp.в этом.файл 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 красиво @ http://plugins.jquery.com/project/GUID_Helper

jQuery.Guid.Value()

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


jQuery.Guid.New()

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


jQuery.Guid.Empty()

возвращает пустую 00000000-0000-0000-0000-000000000000 идентификатор GUID.


jQuery.Guid.IsEmpty()

возвращает логический. True, если пустой / неопределенный / пустой / null.


jQuery.Guid.IsValid()

возвращает логическое значение. True действительный идентификатор guid, false если нет.


jQuery.Guid.Set()

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


образец ES6

const guid=()=> {
  const s4=()=> Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);     
  return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4() + s4() + s4()}`;
}

этот основан на дате и добавляет случайный суффикс для "обеспечения" уникальности. Хорошо работает для идентификаторов 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 Я готов поспорить, большинство из них тоже работают в браузере.