Имеют ли объекты/переменные JavaScript какой-то уникальный идентификатор? Как у Руби есть object_id
. Я имею в виду не атрибут id DOM, а какой-то адрес памяти.
Идентификатор объекта JavaScript
Ответы (4)
Нет, у объектов нет встроенного идентификатора, хотя вы можете добавить его, изменив прототип объекта. Вот пример того, как вы можете это сделать:
(function() {
var id = 0;
function generateId() { return id++; };
Object.prototype.id = function() {
var newId = generateId();
this.id = function() { return newId; };
return newId;
};
})();
Тем не менее, в целом изменение прототипа объекта считается очень плохой практикой. Вместо этого я бы рекомендовал вам вручную назначать идентификатор объектам по мере необходимости или использовать функцию touch
, как предлагали другие.
toString
и используя их вот так id = new Id(); cache[id] = obj
. Это немного орехи, но довольно интересно. Вот статья, которую я написал, в которой более подробно объясняется этот метод: xavi.co/articles /fun-with-tostring-in-javascript
- person Xavi; 06.08.2013
Если вы хотите найти/связать объект с уникальным идентификатором без изменения базового объекта, вы можете использовать WeakMap
:
// Note that object must be an object or array,
// NOT a primitive value like string, number, etc.
var objIdMap=new WeakMap, objectCount = 0;
function objectId(object){
if (!objIdMap.has(object)) objIdMap.set(object,++objectCount);
return objIdMap.get(object);
}
var o1={}, o2={}, o3={a:1}, o4={a:1};
console.log( objectId(o1) ) // 1
console.log( objectId(o2) ) // 2
console.log( objectId(o1) ) // 1
console.log( objectId(o3) ) // 3
console.log( objectId(o4) ) // 4
console.log( objectId(o3) ) // 3
Использование WeakMap
вместо Map
гарантирует, что объекты все еще могут быть удалены сборщиком мусора.
На самом деле вам не нужно изменять прототип object
. Следующее должно работать, чтобы «получить» уникальные идентификаторы для любого объекта достаточно эффективно.
var __next_objid=1;
function objectId(obj) {
if (obj==null) return null;
if (obj.__obj_id==null) obj.__obj_id=__next_objid++;
return obj.__obj_id;
}
Я только что наткнулся на это и подумал, что добавлю свои мысли. Как предлагали другие, я бы рекомендовал вручную добавлять идентификаторы, но если вы действительно хотите что-то близкое к тому, что вы описали, вы можете использовать это:
var objectId = (function () {
var allObjects = [];
var f = function(obj) {
if (allObjects.indexOf(obj) === -1) {
allObjects.push(obj);
}
return allObjects.indexOf(obj);
}
f.clear = function() {
allObjects = [];
};
return f;
})();
Вы можете получить идентификатор любого объекта, вызвав objectId(obj)
. Затем, если вы хотите, чтобы идентификатор был свойством объекта, вы можете либо расширить прототип:
Object.prototype.id = function () {
return objectId(this);
}
или вы можете вручную добавить идентификатор к каждому объекту, добавив аналогичную функцию в качестве метода.
Основное предостережение заключается в том, что это предотвратит уничтожение объектов сборщиком мусора, когда они выпадают из области видимости... они никогда не выпадают из области действия массива allObjects
, поэтому вы можете столкнуться с утечкой памяти. Если вы решили использовать этот метод, вам следует делать это только для целей отладки. При необходимости вы можете выполнить objectId.clear()
, чтобы очистить allObjects
и позволить сборщику мусора выполнить свою работу (но с этого момента все идентификаторы объектов будут сброшены).