У объектов или переменных JavaScript есть свой уникальный идентификатор? Как Ruby имеет object_id
. Я не имею в виду атрибут DOM id, а скорее какой-то адрес памяти.
Идентификатор объекта JavaScript
Ответ 1
Нет, объекты не имеют встроенного идентификатора, хотя вы можете добавить его, изменив прототип объекта. Вот пример того, как вы можете это сделать:
(function() {
var id = 0;
function generateId() { return id++; };
Object.prototype.id = function() {
var newId = generateId();
this.id = function() { return newId; };
return newId;
};
})();
Тем не менее, в целом модификация прототипа объекта считается очень плохой практикой. Вместо этого я рекомендовал бы вам вручную назначить id объектам по мере необходимости или использовать функцию touch
, как предложили другие.
Ответ 2
Если вы хотите найти/связать объект с уникальным идентификатором без изменения базового объекта, вы можете использовать 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
гарантирует, что объекты все еще могут быть собраны в мусор.
Ответ 3
На самом деле вам не нужно изменять прототип 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;
}
Ответ 4
Я только что наткнулся на это и подумал, что добавлю свои мысли. Как и другие, я рекомендую вручную добавлять идентификаторы, но если вы действительно хотите что-то близкое к тому, что вы описали, вы можете использовать это:
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)
. Затем, если вы хотите, чтобы id являлся свойством объекта, вы можете либо расширить прототип:
Object.prototype.id = function () {
return objectId(this);
}
или вы можете вручную добавить идентификатор к каждому объекту, добавив аналогичную функцию как метод.
Основная оговорка заключается в том, что это предотвратит уничтожение сборщика мусора от объектов, когда они выйдут из области видимости... они никогда не выйдут из области массива allObjects
, так что вы можете обнаружить утечки памяти - проблема, Если ваш набор использует этот метод, вы должны сделать это только для целей отладки. При необходимости вы можете сделать objectId.clear()
, чтобы очистить allObjects
и дать GC выполнить свое задание (но с этой точки все идентификаторы объекта будут reset).