Hash/associative array using several objects as ke

2019-02-28 13:40发布

问题:

Is there a way of making an associative array where each key is a hash of several objects? I'm not interested in inspecting each object's state, but rather the object's identity.

 var myarray = {};

 var a = new A();
 var b = new B();
 var c = new C();

 // + is not right, but illustrates the hashing I'm after.
 myarray[a + b + c] = 42;

The + operator is not right. In java I would arithmetically combine the System.identityHashCode() for each of these three instances and use the result to make my new hash key. Is there some similar mechanic in javascript?

Overriding the .toString() method in A, B and C is not an option since I'm interested in object identity, not state.

回答1:

Actually impossible since Object keys in this language only can be strings and there's no equivalent of java's object identity.

:o)



回答2:

You could overwrite the toString() method of the prototypes to create a unique hash for each instance. E.g.

A.prototype.toString = function() {
    return /* something instance specific here */;
};

Even a + b + c would work then.

Update: Afaik, you cannot get an instance unique id (whatever that is) in JavaScript. You could however assign each instance some identifier.

This only works if you are creating the objects.

E.g.

var addIdentityTracker = (function() {
    var pad = "0000000000",
        id = 1;

    function generateId() {
         var i = (id++).toString();
         return pad.substr(0, 10 - i.length) + i;
    }

    return function(Constr) {
        var new_constr = function() {
            this.___uid = generateId();
            Constr.apply(this, arguments);
        };
        new_constr.prototype = Constr.prototype;

        new_constr.prototype.toString = function() {
            return this.___uid;
        };

        return new_constr;
     };
}());

and then do:

A = addIdentityTracker(A);
var a = new A();


回答3:

I'd suggest just assigning a unique ID to each object. Javascript doesn't come with a built-in unique ID mechanism, but you can assign a unique ID to any object you want and then use it as such. For example, you could do this:

// getUniqueID is a function that returns a unique ID for any javascript object.
// If no uniqueID is already present on the object, it coins one using a global
// counter and then stores it on the object.
// So that the uniqueID can be combined with other uniqueIDs easily and still
// create a unique union, the uniqueID here is a unique 10 character string.  
// There is no randomness in the IDs as they are only required to be unique 
// within the page, not random or unique in the universe.  The monotomically 
// increasing counter guarantees uniqueness within the page. 

// Two globals we need for generating the unique ID    
var idCntr = 0;
var controlStr = "0000000000";  // 10 digits long

function getUniqueID(o) {
   if (!o.uniqueID) {
       var base = idCntr++ + "";  // get string version of idCntr
       o.uniqueID = controlStr.slice(0, controlStr.length - base.length) + base;  // zero pad
    }
    return(o.uniqueID);
}

var myobj = {};

var a = new A();
var b = new B();
var c = new C();

myobj[getUniqueID(a) + getUniqueID(b) + getUniqueID(c)] = 42;

For you to fetch the same object back in the future, you'd have to combine the objects in the proper order again. If that wasn't easy, then you could make sure and always combine them in numeric order with the lowest numbers first so you always got a consistent order.