92

JavaScript 对象/变量是否有某种唯一标识符?像 Ruby 一样object_id。我不是指 DOM id 属性,而是某种内存地址。

4

5 回答 5

64

如果您想在不修改底层对象的情况下查找/关联具有唯一标识符的对象,您可以使用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

使用 aWeakMap而不是Map确保对象仍然可以被垃圾收集。

于 2016-02-10T02:56:33.040 回答
51

不,对象没有内置标识符,尽管您可以通过修改对象原型来添加一个。以下是您可以如何执行此操作的示例:

(function() {
    var id = 0;

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

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

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

        return newId;
    };
})();

也就是说,通常修改对象原型被认为是非常糟糕的做法。相反,我建议您根据需要手动为对象分配 id 或使用touch其他人建议的函数。

于 2010-01-07T14:14:45.720 回答
11

实际上,您不需要修改object原型。以下应该足以有效地“获取”任何对象的唯一 ID。

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;
}
于 2012-03-31T15:46:47.683 回答
2

我刚刚遇到这个,并认为我会添加我的想法。正如其他人所建议的那样,我建议手动添加 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;
})();

您可以通过调用来获取任何对象的 ID objectId(obj)。然后,如果您希望 id 成为对象的属性,您可以扩展原型:

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

或者您可以通过添加类似的函数作为方法手动为每个对象添加 ID。

主要的警告是,这将防止垃圾收集器在对象退出范围时销毁它们......它们永远不会退出allObjects数组的范围,因此您可能会发现内存泄漏是一个问题。如果您设置使用此方法,则应仅出于调试目的这样做。需要时,您可以objectId.clear()清除allObjectsGC 并让 GC 完成其工作(但从那时起,对象 ID 将全部重置)。

于 2014-04-21T19:12:11.063 回答
0

const log = console.log;

function* generateId() {
  for(let i = 0; ; ++i) {
    yield i;
  }
}

const idGenerator = generateId();

const ObjectWithId = new Proxy(Object, {
  construct(target, args) {
    const instance = Reflect.construct(target, args);
    instance['id'] = idGenerator.next().value;
    return instance;
  }
})

const myObject = new ObjectWithId({
  name: '@@NativeObject'
});

log(myObject.id);

于 2021-12-22T17:52:12.930 回答