создать уникальный id с помощью javascript

у меня есть форма, где пользователь может добавить несколько полей выбора для нескольких городов. Проблема в том, что каждое вновь созданное поле выбора должно иметь уникальный идентификатор. Это можно сделать на JavaScript?

UPDATE: вот часть формы для выбора городов. Также обратите внимание, что я использую php для заполнения городов при выборе определенного состояния.

<form id="form" name="form" method="post" action="citySelect.php">
<select id="state" name="state" onchange="getCity()">
    <option></option>
    <option value="1">cali</option>
    <option value="2">arizona</option>
    <option value="3">texas</option>
</select>
<select id="city" name="city" style="width:100px">

</select>

    <br/>
</form>

вот javascript:

$("#bt").click(function() {

$("#form").append(
       "<select id='state' name='state' onchange='getCity()'>
           <option></option>
           <option value='1'>cali</option>
           <option value='2'>arizona</option>
           <option value='3'>texas</option>
        </select>
        <select id='city' name='city' style='width:100px'></select><br/>"
     );
});

17 ответов


не могли бы вы просто сохранить текущий индекс?

var _selectIndex = 0;

...code...
var newSelectBox = document.createElement("select");
newSelectBox.setAttribute("id","select-"+_selectIndex++);

редактировать

при дальнейшем рассмотрении вы можете предпочесть использовать имена в стиле массива для выбора...

например

<select name="city[]"><option ..../></select>
<select name="city[]"><option ..../></select>
<select name="city[]"><option ..../></select>

затем на стороне сервера в PHP например:

$cities = $_POST['city']; //array of option values from selects

Изменить 2 в ответ на комментарий OP

динамически создавать варианты используя методы DOM можно сделать как следует:

var newSelectBox = document.createElement("select");
newSelectBox.setAttribute("id","select-"+_selectIndex++);

var city = null,city_opt=null;
for (var i=0, len=cities.length; i< len; i++) {
    city = cities[i];
    var city_opt = document.createElement("option");
    city_opt.setAttribute("value",city);
    city_opt.appendChild(document.createTextNode(city));
    newSelectBox.appendChild(city_opt);
}
document.getElementById("example_element").appendChild(newSelectBox);

предполагая, что cities массив уже существует

в качестве альтернативы вы можете использовать метод innerHTML.....

var newSelectBox = document.createElement("select");
newSelectBox.setAttribute("id","select-"+_selectIndex++);
document.getElementById("example_element").appendChild(newSelectBox);

var city = null,htmlStr="";
for (var i=0, len=cities.length; i< len; i++) {
    city = cities[i];
    htmlStr += "<option value='" + city + "'>" + city + "</option>";
}
newSelectBox.innerHTML = htmlStr;

другой способ использовать миллисекундный таймер:

var uniq = 'id' + (new Date()).getTime();

var id = "id" + Math.random().toString(16).slice(2)

function uniqueid(){
    // always start with a letter (for DOM friendlyness)
    var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65));
    do {                
        // between numbers and characters (48 is 0 and 90 is Z (42-48 = 90)
        var ascicode=Math.floor((Math.random()*42)+48);
        if (ascicode<58 || ascicode>64){
            // exclude all chars between : (58) and @ (64)
            idstr+=String.fromCharCode(ascicode);    
        }                
    } while (idstr.length<32);

    return (idstr);
}

очень короткая функция даст вам уникальный идентификатор:

var uid = (function(){var id=0;return function(){if(arguments[0]===0)id=0;return id++;}})();

alert ( uid ());


в ответ на @scott : Иногда JS идет очень быстро... так...

var uniqueId = null,
    getUniqueName = function(prefix) {
        if (!uniqueId) uniqueId = (new Date()).getTime();
        return (prefix || 'id') + (uniqueId++);
    };

поместите в пространство имен экземпляр, подобный следующему

var myns = {/*.....*/};
myns.uid = new function () {
    var u = 0;
    this.toString = function () {
        return 'myID_' + u++;
    };
};
console.dir([myns.uid, myns.uid, myns.uid]);

Я работаю над аналогичной проблемой с OP и обнаружил, что элементы решений от @Guy и @Scott могут быть объединены для создания решения, которое является более твердым IMO. Полученный уникальный идентификатор здесь имеет три раздела, разделенных подчеркиванием:

  1. ведущий письмо;
  2. метка времени, отображаемая в базе 36;
  3. и последний, случайный раздел.

Это решение должно работать очень хорошо, даже для очень больших наборы:

function uniqueId () {
    // desired length of Id
    var idStrLen = 32;
    // always start with a letter -- base 36 makes for a nice shortcut
    var idStr = (Math.floor((Math.random() * 25)) + 10).toString(36) + "_";
    // add a timestamp in milliseconds (base 36 again) as the base
    idStr += (new Date()).getTime().toString(36) + "_";
    // similar to above, complete the Id using random, alphanumeric characters
    do {
        idStr += (Math.floor((Math.random() * 35))).toString(36);
    } while (idStr.length < idStrLen);

    return (idStr);
}

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

var id = "item"+(new Date()).getMilliseconds()+Math.floor(Math.random()*1000);
 // or use any random number generator
 // whatever prefix can be used instead of "item"
while(document.getElementById(id))
    id += 1;
//# set id right here so that no element can get that id between the check and setting it

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


вот функция (функция genID () ниже), которая рекурсивно проверяет DOM на уникальность на основе любого префекта id / ID, который вы хотите.

в вашем случае вы могли бы использовать его в качестве такового

var seedNum = 1;
newSelectBox.setAttribute("id",genID('state-',seedNum));

function genID(myKey, seedNum){
     var key = myKey + seedNum;
     if (document.getElementById(key) != null){
         return genID(myKey, ++seedNum);
     }
     else{
         return key;
     }
 }

вы можете создать идентификатор с помощью таймера и избегая повторений используя performance.now():

id = 'id' + performance.now()
dup = 'id' + performance.now()

console.log(id)
console.log(id.replace('.','')) // sexy id
console.log(id === dup) // false!
.as-console-wrapper{border-top: none !important;overflow-y: auto !important;top: 0;}

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


вот мой собственный взгляд на него на основе xpath созданного элемента:

/** Returns the XPATH of an element **/
var getPathTo = function(element) {
  if (element===document.body)
      return element.tagName;

  var ix= 0;
  var siblings= element.parentNode.childNodes;
  for (var i= 0; i<siblings.length; i++) {
      var sibling= siblings[i];
      if (sibling===element)
          // stripped xpath (parent xpath + tagname + index)
          return getPathTo(element.parentNode)+ element.tagName + ix+1;
      if (sibling.nodeType===1 && sibling.tagName===element.tagName)
          ix++;
   }
}

/** hashcode function (credit http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery **/
var hashCode = function(str) {
  var hash = 0, i, chr, len;
  if (str.length === 0) return hash;
  for (i = 0, len = str.length; i < len; i++) {
    chr   = str.charCodeAt(i);
    hash  = ((hash << 5) - hash) + chr;
    hash |= 0; // Convert to 32bit integer
 }
return hash;
};

/** Genaretes according to xpath + timestamp **/
var generateUID = function(ele)
{
  return hashCode(getPathTo(ele)) + new Date().getTime();
}

сначала извлекается xpath элемента.

затем вычисляется хэш-код xpath. Поэтому у нас есть уникальный идентификатор на xpath.

проблема здесь в том, что xpath не обязательно уникальны, если уникальные элементы генерируются на лету. Таким образом мы добавляем метку в конце.

возможно, мы могли бы также гарантировать более уникальные элементы, добавив окончательный Математика.Случайный.)(


вы могли бы использовать closure.

var i = 0;
function generateId() {
    return i++;
}

если вы хотите заключить:

function generator() {
  var i = 0;
  return function() {
    return i++;
  };
}

var generateId = generator();
generateId(); //1
generateId(); //2

generator может принимать префикс по умолчанию;generateId coud принимает необязательный суффикс:

function generator(prefix) {
  var i = 0;
  return function(suffix) {
    return prefix + (i++) + (suffix || '');
  };
}

var generateId = generator('_');
generateId('_'); //_1_
generateId('@'); //_2@

это пригодится, если вы хотите, чтобы Ваш идентификатор указывал последовательность, очень похожую на new Date().getTime(), но легче читать.


Я использую следующую функцию:

function (baseId) {
  return baseId + '-' + Math.random().toString(16).slice(2);
}

в параметре baseId Я указываю префикс для id, чтобы было легче идентифицировать элементы.


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

вы можете использовать lodash это uniqueId (документация здесь). Это не хороший генератор uniqueId для, скажем, записей db или вещей, которые будут сохранять сеанс в браузере или что-то в этом роде. Но причина, по которой я пришел сюда в поисках этого, была решена с его помощью. Если вам нужен уникальный id для чего-то достаточно преходящего это подойдет.

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


объединение random & date в ms должно сделать трюк почти без изменения столкновения:

function uniqid(){
  return Math.random().toString(16).slice(2)+(new Date()).getTime()+Math.random().toString(16).slice(2);
}
alert(uniqid()+"\r"+uniqid());