JavaScript 对象/变量是否有某种唯一标识符?像 Ruby 一样object_id
。我不是指 DOM id 属性,而是某种内存地址。
5 回答
如果您想在不修改底层对象的情况下查找/关联具有唯一标识符的对象,您可以使用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
确保对象仍然可以被垃圾收集。
不,对象没有内置标识符,尽管您可以通过修改对象原型来添加一个。以下是您可以如何执行此操作的示例:
(function() {
var id = 0;
function generateId() { return id++; };
Object.prototype.id = function() {
var newId = generateId();
this.id = function() { return newId; };
return newId;
};
})();
也就是说,通常修改对象原型被认为是非常糟糕的做法。相反,我建议您根据需要手动为对象分配 id 或使用touch
其他人建议的函数。
实际上,您不需要修改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;
}
我刚刚遇到这个,并认为我会添加我的想法。正如其他人所建议的那样,我建议手动添加 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()
清除allObjects
GC 并让 GC 完成其工作(但从那时起,对象 ID 将全部重置)。
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);