JavaScript对象/变量是否有某种唯一标识符?像Ruby有object_id
一样。我不是指DOM id属性,而是某种内存地址。
JavaScript对象/变量是否有某种唯一标识符?像Ruby有object_id
一样。我不是指DOM id属性,而是某种内存地址。
如果您想查找/关联一个具有唯一标识符的对象而不修改底层对象,您可以使用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
可以确保对象仍然能够进行垃圾回收。
不,对象没有内置标识符,但你可以通过修改对象原型来添加一个标识符。下面是一个如何实现的例子:
(function() {
var id = 0;
function generateId() { return id++; };
Object.prototype.id = function() {
var newId = generateId();
this.id = function() { return newId; };
return newId;
};
})();
话虽如此,一般来说修改对象原型被认为是非常糟糕的做法。我建议您根据需要手动分配对象ID或像其他人建议的那样使用touch
函数。
toString
方法来实现 "id 对象",并像这样使用它们:id = new Id(); cache[id] = obj
。这有点疯狂,但非常有趣。这是一篇我写的文章,更详细地解释了这个技巧:http://xavi.co/articles/fun-with-tostring-in-javascript - Xavi实际上,您不需要修改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;
}
我刚刚看到这篇文章,想分享我的想法。正如其他人所建议的那样,我建议手动添加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。如果您希望该ID成为对象的属性,则可以扩展原型:
Object.prototype.id = function () {
return objectId(this);
}
或者你可以通过添加类似的方法手动为每个对象添加一个ID来实现。
主要的注意点是这将阻止垃圾回收器在对象超出作用域时销毁它们...它们永远不会超出allObjects
数组的作用域,因此您可能会发现内存泄漏是一个问题。如果您坚持使用此方法,应仅在调试目的时使用。需要时,您可以执行objectId.clear()
来清除allObjects
并让GC完成其工作(但从那时起,所有对象ID都将被重置)。
var objectId = (function() {
var mem = [];
var f = function(obj) {
var r = mem.indexOf(obj);
if (r === -1) {
r = mem.length;
mem.push(obj);
}
return r;
};
f.reset = function() {
return mem = [];
};
return f;
})();
- luochen1990const 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);