Unique identifier of an object in javascript

I need to do some kind of experiment, and I need to know some unique identifier for the objects in javascript, so I can understand if they match. I don't want to use equality operators, I need something like the id () function in python.

Is there something similar?

+108
javascript
Jan 04 2018-10-10T00:
source share
10 answers

Update My original answer below was written 6 years ago in a style that suits me and my understanding. In response to some conversation in the comments, a more modern approach to this is as follows:

(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` 

If you have requirements for an archaic browser, check here for browser compatibility for Object.defineProperty .

The original answer is saved below (and not just in the history of changes), because I believe that the comparison is valuable.




You can give the next rotation. It also gives you the ability to explicitly set the identifier of an object in its constructor or elsewhere.

 (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()); 

Make sure that any member that you use to store the unique identifier internally does not encounter another automatically created member name.

+62
Jan 04 '10 at 6:26
source share

To my knowledge, any answer posted here can have unexpected side effects.

In an ES2015-compatible environment, you can avoid any side effects using 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 
+37
May 14 '17 at 11:59 a.m.
source share

Recent browsers provide a cleaner method for extending Object.prototype. This code will make the property hidden from listing properties (for p to o)

For browsers that implement defineProperty , you can implement the uniqueId property as follows:

 (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; } }); }()); 

See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty for details

+35
Sep 28 2018-11-11T00:
source share

In fact, you do not need to modify the prototype object and add a function there. The following should work well for your purpose.

 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; } 
+10
Mar 31 '12 at 15:48
source share

For browsers that implement the Object.defineProperty() method, the code below generates and returns a function that you can bind to any own object.

This approach has the advantage that it does not extend Object.prototype .

The code works by checking whether the given object has the __objectID__ property, and defining it as a hidden (non-enumerable) read-only property, if not.

Thus, it is safe against any attempt to change or override the read-only property obj.__objectID__ after it has been defined, and consistently produces a nice error instead of silence.

Finally, in a rather extreme case, when some other code has already defined __objectID__ for this object, this value will simply be returned.

 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__; } }; })(); 
+6
Nov 23 '12 at 15:59
source share

JQuery code uses its own data() method as such an identifier.

 var id = $.data(object); 

In the behind-the-scenes data method, a very special field is created in the object , called "jQuery" + now() , which puts the next identifier for the stream of unique identifiers of the type

 id = elem[ expando ] = ++uuid; 

I would suggest using the same method as John Resig, obviously, knows all that is about JavaScript, and his method is based on all this knowledge.

+3
Jan 04 '10 at 6:33
source share

Typescript version of @justin answer, compatible with ES6, using characters to prevent any clash of keys and add to the global Object.id for convenience. Just copy paste the code below or put it in the ObjecId.ts file that you import.

 (enableObjectID)(); const uniqueId: symbol = Symbol('The unique id of an object'); function enableObjectID(): void { if (typeof Object['id'] !== 'undefined') { return; } let id: number = 0; Object['id'] = (object: any) => { const hasUniqueId: boolean = !!object[uniqueId]; if (!hasUniqueId) { object[uniqueId] = ++id; } return object[uniqueId]; }; } 

Use in your ts code:

 (<any>Object).id(yourObject); 
+3
Sep 01 '17 at 9:08 on
source share

I used code that would make objects scribble using unique lines:

 Object.prototype.__defineGetter__('__id__', function () { var gid = 0; return function(){ var id = gid++; this.__proto__ = { __proto__: this.__proto__, get __id__(){ return id } }; return id; } }.call() ); Object.prototype.toString = function () { return '[Object ' + this.__id__ + ']'; }; 

the __proto__ bit should hold the __id__ getter in the object. this has been tested only in firefox.

+1
Jan 04 '10 at 7:17
source share

Despite recommendations not to modify Object.prototype, it can be really useful for testing in a limited area. The author of the accepted answer changed it, but still sets Object.id , which for me does not make sense. Here is a snippet that does the job:

 // Generates a unique, read-only id for an object. // The _uid is generated for the object the first time it accessed. (function() { var id = 0; Object.defineProperty(Object.prototype, '_uid', { // The prototype getter sets up a property on the instance. Because // the new instance-prop masks this one, we know this will only ever // be called at most once for any given object. get: function () { Object.defineProperty(this, '_uid', { value: id++, writable: false, enumerable: false, }); return this._uid; }, enumerable: false, }); })(); function assert(p) { if (!p) throw Error('Not!'); } var obj = {}; assert(obj._uid == 0); assert({}._uid == 1); assert([]._uid == 2); assert(obj._uid == 0); // still 
+1
May 10 '16 at 4:58
source share

I ran into the same problem and here is the solution that I implemented with ES6

 code let id = 0; // This is a kind of global variable accessible for every instance class Animal { constructor(name){ this.name = name; this.id = id++; } foo(){} // Executes some cool stuff } cat = new Animal("Catty"); console.log(cat.id) // 1 
+1
Dec 01 '16 at 21:06
source share



All Articles