我需要做一些实验,我需要知道 javascript 中对象的某种唯一标识符,以便我可以查看它们是否相同。我不想使用相等运算符,我需要类似 python 中的 id() 函数的东西。
这样的东西存在吗?
我需要做一些实验,我需要知道 javascript 中对象的某种唯一标识符,以便我可以查看它们是否相同。我不想使用相等运算符,我需要类似 python 中的 id() 函数的东西。
这样的东西存在吗?
更新我下面的原始答案是 6 年前以适合时代和我的理解的风格写的。针对评论中的一些对话,更现代的方法如下:
(function() {
if ( typeof Object.id == "undefined" ) {
var id = 0;
Object.id = function(o) {
if ( typeof o.__uniqueid == "undefined" ) {
Object.defineProperty(o, "__uniqueid", {
value: ++id,
enumerable: false,
// This could go either way, depending on your
// interpretation of what an "id" is
writable: false
});
}
return o.__uniqueid;
};
}
})();
var obj = { a: 1, b: 1 };
console.log(Object.id(obj));
console.log(Object.id([]));
console.log(Object.id({}));
console.log(Object.id(/./));
console.log(Object.id(function() {}));
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
console.log(k);
}
}
// Logged keys are `a` and `b`
如果您有过时的浏览器要求,请在此处查看Object.defineProperty
.
原始答案保留在下面(而不仅仅是在更改历史记录中),因为我认为比较是有value的。
您可以尝试以下内容。这也使您可以选择在其构造函数或其他地方显式设置对象的 ID。
(function() {
if ( typeof Object.prototype.uniqueId == "undefined" ) {
var id = 0;
Object.prototype.uniqueId = function() {
if ( typeof this.__uniqueid == "undefined" ) {
this.__uniqueid = ++id;
}
return this.__uniqueid;
};
}
})();
var obj1 = {};
var obj2 = new Object();
console.log(obj1.uniqueId());
console.log(obj2.uniqueId());
console.log([].uniqueId());
console.log({}.uniqueId());
console.log(/./.uniqueId());
console.log((function() {}).uniqueId());
请注意确保用于内部存储唯一 ID 的任何成员都不会与另一个自动创建的成员名称冲突。
就我的观察而言,此处发布的任何答案都可能产生意想不到的副作用。
在 ES2015 兼容的环境中,您可以通过使用WeakMap来避免任何副作用。
const id = (() => {
let currentId = 0;
const map = new WeakMap();
return (object) => {
if (!map.has(object)) {
map.set(object, ++currentId);
}
return map.get(object);
};
})();
id({}); //=> 1
最新的浏览器为扩展 Object.prototype 提供了一种更简洁的方法。此代码将使属性从属性枚举中隐藏(对于 p in o)
对于实现了 defineProperty的浏览器,您可以像这样实现 uniqueId属性:
(function() {
var id_counter = 1;
Object.defineProperty(Object.prototype, "__uniqueId", {
writable: true
});
Object.defineProperty(Object.prototype, "uniqueId", {
get: function() {
if (this.__uniqueId == undefined)
this.__uniqueId = id_counter++;
return this.__uniqueId;
}
});
}());
有关详细信息,请参阅https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty
实际上,您不需要修改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;
}
对于实现该Object.defineProperty()
方法的浏览器,以下代码生成并返回一个函数,您可以将其绑定到您拥有的任何对象。
这种方法的优点是不扩展Object.prototype
.
该代码的工作原理是检查给定对象是否具有__objectID__
属性,如果没有,则将其定义为隐藏(不可枚举)只读属性。
因此,在定义只读obj.__objectID__
属性后,任何更改或重新定义只读属性的尝试都是安全的,并且始终抛出一个很好的错误而不是静默失败。
最后,在某些其他代码已经__objectID__
在给定对象上定义的非常极端的情况下,将简单地返回该值。
var getObjectID = (function () {
var id = 0; // Private ID counter
return function (obj) {
if(obj.hasOwnProperty("__objectID__")) {
return obj.__objectID__;
} else {
++id;
Object.defineProperty(obj, "__objectID__", {
/*
* Explicitly sets these two attribute values to false,
* although they are false by default.
*/
"configurable" : false,
"enumerable" : false,
/*
* This closure guarantees that different objects
* will not share the same id variable.
*/
"get" : (function (__objectID__) {
return function () { return __objectID__; };
})(id),
"set" : function () {
throw new Error("Sorry, but 'obj.__objectID__' is read-only!");
}
});
return obj.__objectID__;
}
};
})();