37

Converting objects to hash signatures in JavaScript

 5 years ago
source link: https://www.tuicool.com/articles/hit/VzMVF3Y
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Sometimes, comparing plain-old-javascript-objects (POJOs) to other POJOs is time consuming, there should be a simple way to calculate a consistent signature of the object for comparison. After a few experiments, and some research, I've found a fast and safe way to do hash comparison with static or dynamic objects not dependant on the same data structure, only using properties existing on the object itself. Part two is available here, where we discuss and implement dynamic property iteration , while using signatures.

Breaking it down

If you wanted to compare two objects of the same type, say Person , we want to know if they're identical, or different, and if different, what properties can we determine are different?

Our person object will look similar to this:

var Bob = {
    name: "Bob Smith",
    age: 43,
    occupation: "Software Engineer",
    goal: "Become Engineering Team Leader"
};

var Alice = {
    name: "Alice Wonderfan",
    age: 22,
    occupation: "Software Engineer"
    goal: "Become a chef"
};

We can see the objects are different when reviewing, but from a code standpoint where there is no assurance, and no manual review as the data is dynamic, we need a simple performance-optimised way to calculate the difference, that's why the Object Signature functionality below comes in handy.

image-4.png

Introducing Object Signatures

Object Signatures is a reproducible, consistent hash based on local object properties, in order to calculate the hash, we need to know some of our local members on the object, regardless if they're in an null/undefined state or not, then we chop through the array of data joining using a shared object constant, we build a hash for the data, and convert it to a 32bit integer. It is important to note this integer can be both negative and positive, depending on the data that is on the object. Now let's dive into the code:

Person.prototype.getSignature = function() {

    var joiner = [ this.name, this.age, this.occupation, this.goal ].join(SIGNATURE_OFFSET); // for example, SIGNATURE_OFFSET='-'

    var hash = 0, index, character;

    for(index = 0; index < joiner.length; index++)
    {
    
        character = joiner.charCodeAt(index);
        
        hash = ( ( hash << 5 ) - hash ) + character; // effectively, hash * 31 - hash + character offset
        
        hash |= 0; // this is a bitwise OR operand
    }
    
    return hash;
};

Now, if I were to construct two person objects like above, the signature generation method will join the name, age, occupation, and goals into one string, covert the string to their character codes, do some quick maths using bitwise operations, and return the hash it's calculated.

If you were to compare the two objects, you can do something similar to this:

var bob_sig = Bob.getSignature();
var alice_sig = Alice.getSignature();
if( bob_sig === alice_sig ) { alert('They\'re twins!'); }
if( bob_sig !== alice_sig ) { alert('They\'re not twins!'); }

It's important to note this approach can be expanded to have a method passing in the data, changing the joiner to join the array by the SIGNATURE_OFFSET, and let the caller specify the details, however, I personally prefer letting the objects dictate their own guaranteed properties , a generic implementation can be applied on the Object prototype, with you supplying the data to be joined and compared against.

That's all for now, hopefully you've learned something about how bitwise and signature generation works. Part two is available here, where we discuss and implement dynamic property iteration, while using signatures.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK