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

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

4 ответов


нет, объекты не имеют встроенного идентификатора, хотя вы можете добавить его, изменив прототип объекта. Вот пример того, как вы можете это сделать:

(function() {
    var id = 0;

    function generateId() { return id++; };

    Object.prototype.id = function() {
        var newId = generateId();

        this.id = function() { return newId; };

        return newId;
    };
})();

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


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


на самом деле, вам не надо изменять 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). Затем, если вы хотите, чтобы id был свойством объекта, вы можете либо расширить прототип:

Object.prototype.id = function () {
    return objectId(this);
}

или вы можете вручную добавить ID к каждому объекту, добавив аналогичную функцию в качестве метод.

главное предостережение заключается в том, что это предотвратит сборщик мусора от уничтожения объектов, когда они выпадут из сферы действия... они никогда не выпадут из сферы allObjects массив, поэтому вы можете обнаружить, что утечки памяти являются проблемой. Если ваш набор использует этот метод,вы должны сделать это только для отладки. При необходимости, вы можете сделать objectId.clear() очистить allObjects и пусть GC выполняет свою работу (но с этого момента идентификаторы объектов будут сброшены).