JavaScript对象Id
JavaScript对象/变量是否具有某种唯一标识符?就像Ruby有JavaScript对象Id,javascript,unique-id,Javascript,Unique Id,JavaScript对象/变量是否具有某种唯一标识符?就像Ruby有对象id。我指的不是DOM id属性,而是某种内存地址。不,对象没有内置标识符,不过可以通过修改对象原型添加一个标识符。下面是一个示例,说明了如何做到这一点: (function() { var id = 0; function generateId() { return id++; }; Object.prototype.id = function() { var newId = g
对象id
。我指的不是DOM id属性,而是某种内存地址。不,对象没有内置标识符,不过可以通过修改对象原型添加一个标识符。下面是一个示例,说明了如何做到这一点:
(function() {
var id = 0;
function generateId() { return id++; };
Object.prototype.id = function() {
var newId = generateId();
this.id = function() { return newId; };
return newId;
};
})();
也就是说,一般来说,修改对象原型被认为是非常糟糕的做法。相反,我建议您根据需要手动为对象分配id,或者像其他人建议的那样使用
touch
功能。实际上,您不需要修改对象
原型。以下内容可以有效地“获取”任何对象的唯一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;
})();
您可以通过调用objectId(obj)
获取任何对象的ID。然后,如果希望id成为对象的属性,可以扩展原型:
Object.prototype.id = function () {
return objectId(this);
}
或者,您可以通过添加与方法类似的函数,手动向每个对象添加ID
主要的警告是,这将防止垃圾收集器在对象退出范围时销毁它们。。。它们永远不会退出
allObjects
数组的范围,所以您可能会发现内存泄漏是一个问题。如果设置为使用此方法,则只应出于调试目的而这样做。需要时,您可以执行objectId.clear()
以清除allObjects
,并让GC执行其工作(但从那时起,对象ID将全部重置)。如果您希望在不修改基础对象的情况下查找/关联具有唯一标识符的对象,可以使用:
//注意对象必须是对象或数组,
//不是字符串、数字等基本值。
var objIdMap=new WeakMap,objectCount=0;
函数objectId(object){
如果(!objIdMap.has(object))objIdMap.set(object,++objectCount);
返回objIdMap.get(object);
}
VarO1={},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
可以确保对象仍然可以被垃圾收集。您是否希望使用对象id来比较对象?请看,这肯定不是真的,因为问题在别处得到了回答。甚至都不接近。@ErikAronesty我同意。在链接线程中,没有任何地方可以回答对象是否具有内置id的问题。请注意,如果您希望对象之后具有不同的id,那么这将无法很好地处理大多数复制对象的方法。事实上,您需要一个特殊的“copyObject”函数来专门考虑这个id。您还必须确保与在其他库中使用“\uuuuobj\uid”没有冲突。这在ActionScript中要容易得多,它的Dictionary对象对键(包括用作键的对象)使用严格的相等比较。事实上,您可能可以在JS中编写一个字典类,以这种方式自动将ID附加到作为键添加到其中的对象。这就像量子力学;在你尝试用这个函数观察它们之前,它们是不存在的。haha.ActionScript 3有一个字典对象,它使用严格的相等性进行键比较,因此可以使用对象作为键。JavaScript中是否有等价物,或者您是否必须为每个对象手动构造唯一的id(通过object.prototype或手动添加id来选择对象)?不幸的是,JavaScript没有类似的功能。听起来您必须给对象id,然后按照您的建议将这些id用作对象中的键。也就是说,如果你真的想变得聪明,你可以通过重写toString
方法实现“id对象”,并像这样使用它们id=newid();cache[id]=obj
。这有点疯狂,但很有趣。下面是我写的一篇文章,更详细地解释了这种技术:好吧,我刚刚找到了原因。jQuery还覆盖了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;}();“``@loochen1990,我想你会对它的速度感到惊讶。(但是你是对的,最好是把index()放进去)结果是一个变量,尽管我会从枯燥的角度而不是从优化的角度来论证。)只要GC问题能够得到有效管理,我认为您必须拥有大量的对象才能注意到任何显著的性能影响。最佳答案!使用内存O(n),其中n是您关心的ID的对象数(而不是n=所有对象)并且不影响垃圾收集。好极了!甚至可以在IE11中工作(在Win10上测试)