How to get the identity of an object in Javascript?

Asked

Viewed 603 times

10

Several languages have a means of obtaining the "identity" of an object, i.e. an [integer] number that is unique to each object, such that different objects have different identities. Examples:

As far as reasonably practical, the hashcode method defined by the Object class returns distinct integers for distinct objects. (This is typically implemented by converting the object’s internal address into an integer, but this implementation technique is not required by the Java programming language.)

  • Python (id)

Returns the "identity" of an object. This is an integer (or long integer) that is guaranteed to be unique and constant to that object during its life cycle. Two objects with non-overlapping lifetimes can have the same value for id().

Is there similar functionality in Javascript? Preferably standardized, that worked in all browsers and other environments (Rhino, V8). Searching for "Identity" I only find references to the operator (===)...

I know that some environments do not support this concept (.NET apparently does not do so for reasons of optimization), but in general this is not a problem because they are more complete languages, which have the concepts of destructor, finisher and/or weak references. As far as I know, Javascript does not support this, so a way to get a numeric value that only represents an object would be very useful (a simple reference to the object does not serve as it would prevent it from being collected as garbage).

  • Can you illustrate in what scenario this id would be used? Why would you save the id of an object that has already been collected as garbage?

  • @Rodrigorgs Just to know when and if it was collected as garbage. As Javascript [yet] does not support weak references, and there doesn’t seem to be any workaround satisfactory, my only way out is to try to "simulate" them through an indirect reference (I’m still working on the details). For cases of use for weak references, has an interesting material here (Notice: PDF).

  • The language does not foresee any way to get this type of identity, so if any interpreter includes this, it is in a non-standard way.

2 answers

12


The specification ECMA-262 does not foresee this functionality in the language, and I have no knowledge of any Javascript engine that implements it.

If you want to implement yourself, a starting point is this (based on this reply in English):

(function(){
    var id = 0;
    Object.prototype.getIdentity = function() {
        if(!this.hasOwnProperty('__identity__')) {
            this.__identity__ = ++id;
        }
        return this.__identity__;
    };
}());

Note that __identity__ is a public property that all objects that invoked getIdentity once they become. Therefore nothing prevents it from being manipulated directly, which would potentially compromise the results.

An implementation with features of Ecmascript 5 (i.e., incompatible with older engines like IE8) can prevent this:

(function(){
    var id = 0;
    Object.prototype.getIdentity = function() {
        if(!this.hasOwnProperty('__identity__')) {
            Object.defineProperty(this, '__identity__', { 
                enumerable: false,
                writable: false,
                value: ++id 
            });
        }
        return this.__identity__;
    };
}());

The attribute writable: false ensures that the value of __identity__ cannot be changed manually. E enumerable: false omit the property of enumerations for..in, or serialization via JSON.stringify, as suggested by Talles.

  • I think you’re right. I had already taken a look at the specifications (both the current version and the last draft of version 6) and also found nothing, but I was hoping that there was some obscure functionality that I was not aware of.

  • In version 5.1 I assure you that it does not have. In 6 I doubt, but I do not put my hand in the fire...

  • 1

    I suggest changing this.__identity__ = ++id for Object.defineProperty(this, '__identity__', { enumerable: false, value: ++id }). Thus the property __identity__ will not appear in loops for. in or in a call to JSON.stringify.

  • Thanks, @Talles. I added your suggestion but kept the original version since it works on pre-ES5 implementations. With Object.defineProperty can also prevent __identity__ be changed manually.

1

You can add global functionality to the type String:

String.prototype.hashCode = function(){
    var hash = 0;
    for (var i = 0; i < this.length; i++) {
        var character = this.charCodeAt(i);
        hash = ((hash << 5) - hash) + character;
        hash = hash & hash; // Converte para inteiro 32 bit
    }
    return hash;
}

Source

The library Lo-Dash offers some useful features. One is the possibility to compare the equivalence of two values

http://lodash.com/docs#isEqual

var object = { 'name': 'fred' };
var copy = { 'name': 'fred' };

object == copy;
// → false

_.isEqual(object, copy);
// → true

var words = ['hello', 'goodbye'];
var otherWords = ['hi', 'goodbye'];

_.isEqual(words, otherWords, function(a, b) {
  var reGreet = /^(?:hello|hi)$/i,
      aGreet = _.isString(a) &amp;&amp; reGreet.test(a),
      bGreet = _.isString(b) &amp;&amp; reGreet.test(b);

  return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
});
// → true
  • Thanks for the answer, but unfortunately what I’m looking for is the contrary than you propose: a value that is unique to the object, so that although two objects are identical [but distinct] they still have a different identity. In other words, id(x) == id(y) if and only if x === y.

  • Got it. I believe the only ways in Javascript, that is to keep a hashtable each time an object is created, or transform the function toString to return a unique identifier of the object with a global variable id being increased to every creation.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.