JavaScript Object Id
不,对象没有内置标识符,但可以通过修改对象原型来添加标识符。这里有一个如何做到这一点的例子:
(function() {
var id = 0;
function generateId() { return id++; };
Object.prototype.id = function() {
var newId = generateId();
this.id = function() { return newId; };
return newId;
};
})();
也就是说,在一般情况修改对象原型被认为是非常不好的做法。相反,我会建议您根据需要手动将对象分配给对象,或者像其他人所建议的那样使用touch
函数。
ActionScript 3有一个Dictionary对象,它使用严格的等式进行键比较,因此可以使用对象作为键。在JavaScript中是否存在等价物,或者是否需要为每个对象手动构造唯一的ID(通过Object.prototype或手动添加ID来选择对象)? – Triynko 2013-08-06 06:30:07
不幸的是,JavaScript没有类似的东西。听起来像你必须给对象ID,然后使用这些ID作为对象的键,如你所建议的。也就是说,如果你真的想要聪明,你可以通过重写'toString'方法来实现“id对象”,并像这样使用它们'id = new Id();缓存[id] = obj'。这有点坚果,但很有趣。下面是我写的一篇文章,更详细地解释了这种技术:http://xavi.co/articles/fun-with-tostring-in-javascript – Xavi 2013-08-06 07:03:42
好吧,我刚刚发现了原因。 jQuery也覆盖了ID,当我覆盖它时,我的页面不知何故被破坏。哈。好的。所以。我只是避免命名问题并跨过我的手指。 – Lodewijk 2014-10-19 12:16:21
实际上,您不需要修改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,则这种方法不适用于复制对象的大多数方法。 – 2013-06-09 01:15:37
事实上,你需要一个特殊的“copyObject”函数来专门考虑这个__obj_id。您还必须确保在其他库中使用“__obj_id”没有冲突。这在ActionScript中非常容易,它的Dictionary对象在键上使用严格的相等比较,包括用作键的对象。实际上,你可能可以在JS中编写一个Dictionary类,它自动将ID添加到作为键的对象中。这就像量子力学JavaScript ID一样;他们不存在,直到你试图用这个函数观察它们,哈哈。 – Triynko 2013-08-06 06:38:51
我刚刚遇到过这个,并想我会加上我的想法。正如其他人的建议,我建议你手动添加的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将全部重置)。
我认为这是一个缓慢但健壮的解决方案,并且可以改进一点: ''' 变种的ObjectID =(函数(){ VAR MEM = []; 变种F =函数(OBJ){ VAR R = mem.indexOf(OBJ); 如果(R === -1){ R = mem.length; mem.push(OBJ); } 返回R等 }; f.reset =函数(){ return mem = []; }; return f; })(); ''' – luochen1990 2015-07-04 08:15:45
@ luochen1990,我想你会对它的速度感到惊讶。 (但是你是对的,最好将indexOf()结果放入一个变量中,尽管我会从DRY角度而不是优化来争论它)。只要GC问题能够得到有效管理, d必须有很多对象才能注意到任何显着的性能影响。 – 2015-07-07 11:36:12
如果要查找/与唯一标识符的对象,而无需修改基本对象相关联,则可以使用一个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
确保对象仍可以是垃圾收集。
最佳答案!使用内存O(n),其中n是您关心其ID的对象的数量(而不是n =所有对象),并且不影响垃圾回收。 – 2018-01-08 16:48:48
你在比较使用object_id的对象吗? – Upperstage 2010-01-07 14:16:51
请参阅http://stackoverflow.com/questions/1997661/unique-object-identifier-in-javascript – 2010-01-07 15:34:17