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

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


person treznik    schedule 07.01.2010    source источник
comment
Вы хотите сравнить объекты, используя object_id?   -  person Upperstage    schedule 07.01.2010
comment
См. stackoverflow.com/questions/1997661/   -  person Crescent Fresh    schedule 07.01.2010
comment
это определенно неправда, что на этот вопрос дан ответ в другом месте. даже не близко.   -  person Erik Aronesty    schedule 25.06.2020
comment
@ErikAronesty Я согласен. Нигде в связанной ветке нет ответа на вопрос, есть ли у объектов встроенный идентификатор.   -  person BobRodes    schedule 25.02.2021


Ответы (4)


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

(function() {
    var id = 0;

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

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

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

        return newId;
    };
})();

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

person Xavi    schedule 07.01.2010
comment
ActionScript 3 имеет объект Dictionary, который использует строгое равенство для сравнения ключей, поэтому можно использовать объекты в качестве ключей. Есть ли эквивалент в JavaScript, или вам придется вручную создавать уникальные идентификаторы для каждого объекта (либо через Object.prototype, либо вручную добавляя идентификатор для выбора объектов)? - person Triynko; 06.08.2013
comment
К сожалению, в javascript такого нет. Похоже, вам придется указать идентификатор объектов, а затем использовать эти идентификаторы в качестве ключей в объекте, как вы предложили. Тем не менее, если вы действительно хотите быть умным, вы можете реализовать объекты id, переопределив метод toString и используя их вот так id = new Id(); cache[id] = obj. Это немного орехи, но довольно интересно. Вот статья, которую я написал, в которой более подробно объясняется этот метод: xavi.co/articles /fun-with-tostring-in-javascript - person Xavi; 06.08.2013
comment
Хорошо, я только что узнал, почему. jQuery также переопределяет идентификатор, и моя страница каким-то образом сломалась, когда я переопределил ее. Ха. Хорошо. Так. Я просто буду избегать проблем с именами и скрещу пальцы. - person Lodewijk; 19.10.2014
comment
Этот пример можно использовать как отличный пример использования замыканий и прототипного наследования. - person Peter Clause; 01.06.2015

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

person Phrogz    schedule 10.02.2016
comment
Лучший ответ! Использует память O(n), где n — количество объектов, идентификаторы которых вам нужны (а не n = все объекты), и не влияет на сборку мусора. - person Jason Cohen; 08.01.2018
comment
Браво! Работает даже в IE11 (проверено на Win10) - person Breaker222; 04.10.2018

На самом деле вам не нужно изменять прототип 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;
}
person KalEl    schedule 31.03.2012
comment
Просто имейте в виду, что это НЕ будет хорошо работать с большинством способов копирования объектов, если вы ожидаете, что впоследствии объекты будут иметь разные идентификаторы. - person Paul Draper; 09.06.2013
comment
Действительно, вам понадобится специальная функция copyObject, которая специально учитывает этот __obj_id. Вы также должны быть уверены, что нет конфликтов с использованием __obj_id в других библиотеках. Это намного проще в ActionScript, чей объект Dictionary использует строгое сравнение на равенство для ключей, включая объекты, используемые в качестве ключей. На самом деле, вы, вероятно, могли бы написать класс Dictionary в JS, который таким образом автоматически прикрепляет идентификаторы к объектам, которые добавляются к нему в качестве ключей. Это похоже на квантово-механические идентификаторы JavaScript; они не существуют, пока вы не попытаетесь наблюдать за ними с помощью этой функции, ха-ха. - person Triynko; 06.08.2013

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

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 и позволить сборщику мусора выполнить свою работу (но с этого момента все идентификаторы объектов будут сброшены).

person Nathan MacInnes    schedule 21.04.2014
comment
Я думаю, что это медленное, но надежное решение, и его можно немного улучшить: ``` var objectId = (function() { var mem = []; var f = function(obj) { var r = mem.indexOf (obj); если (r === -1) { r = mem.length; mem.push(obj); } return r; }; f.reset = function() { return mem = []; }; return ф; })(); ``` - person luochen1990; 04.07.2015
comment
@luochen1990, я думаю, вы будете удивлены такой скоростью. (Но вы правы, лучше поместить результат indexOf() в переменную, хотя я бы поспорил с точки зрения DRY, а не с точки зрения оптимизации.) Пока проблема GC может быть эффективно решена, я думаю, вы' d должно быть чертовски много объектов, чтобы заметить какое-либо значительное влияние на производительность. - person Nathan MacInnes; 07.07.2015