Подтвердить что ты не робот

Идентификатор объекта JavaScript

У объектов или переменных JavaScript есть свой уникальный идентификатор? Как Ruby имеет object_id. Я не имею в виду атрибут DOM id, а скорее какой-то адрес памяти.

4b9b3361

Ответ 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).