Is there any kind of hash code function in JavaScript?

后端 未结 20 1166
慢半拍i
慢半拍i 2020-12-04 09:59

Basically, I\'m trying to create an object of unique objects, a set. I had the brilliant idea of just using a JavaScript object with objects for the property names. Such as,

相关标签:
20条回答
  • 2020-12-04 10:18

    Here's my simple solution that returns a unique integer.

    function hashcode(obj) {
        var hc = 0;
        var chars = JSON.stringify(obj).replace(/\{|\"|\}|\:|,/g, '');
        var len = chars.length;
        for (var i = 0; i < len; i++) {
            // Bump 7 to larger prime number to increase uniqueness
            hc += (chars.charCodeAt(i) * 7);
        }
        return hc;
    }
    
    0 讨论(0)
  • 2020-12-04 10:20

    Based on the title, we can generate strong SHA hashes, in a browser context, it can be used to generate a unique hash from an object, an array of params, a string, or whatever.

    async function H(m) {
      const msgUint8 = new TextEncoder().encode(m)                       
      const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8)          
      const hashArray = Array.from(new Uint8Array(hashBuffer))                    
      const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
      console.log(hashHex)
    }
    
    /* Examples ----------------------- */
    H("An obscure ....")
    H(JSON.stringify( {"hello" : "world"} ))
    H(JSON.stringify( [54,51,54,47] ))

    The above output in my browser, it should be equal for you too:

    bf1cf3fe6975fe382ab392ec1dd42009380614be03d489f23601c11413cfca2b
    93a23971a914e5eacbf0a8d25154cda309c3c1c72fbb9914d47c60f3cb681588
    d2f209e194045604a3b15bdfd7502898a0e848e4603c5a818bd01da69c00ad19
    

    Supported algos:

    SHA-1 (but don't use this in cryptographic applications)
    SHA-256
    SHA-384
    SHA-512
    

    https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#Converting_a_digest_to_a_hex_string

    0 讨论(0)
  • 2020-12-04 10:23

    If you want to use objects as keys you need to overwrite their toString Method, as some already mentioned here. The hash functions that were used are all fine, but they only work for the same objects not for equal objects.

    I've written a small library that creates hashes from objects, which you can easily use for this purpose. The objects can even have a different order, the hashes will be the same. Internally you can use different types for your hash (djb2, md5, sha1, sha256, sha512, ripemd160).

    Here is a small example from the documentation:

    var hash = require('es-hash');
    
    // Save data in an object with an object as a key
    Object.prototype.toString = function () {
        return '[object Object #'+hash(this)+']';
    }
    
    var foo = {};
    
    foo[{bar: 'foo'}] = 'foo';
    
    /*
     * Output:
     *  foo
     *  undefined
     */
    console.log(foo[{bar: 'foo'}]);
    console.log(foo[{}]);
    

    The package can be used either in browser and in Node-Js.

    Repository: https://bitbucket.org/tehrengruber/es-js-hash

    0 讨论(0)
  • 2020-12-04 10:24

    Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

    you can use Es6 symbol to create unique key and access object. Every symbol value returned from Symbol() is unique. A symbol value may be used as an identifier for object properties; this is the data type's only purpose.

    var obj = {};
    
    obj[Symbol('a')] = 'a';
    obj[Symbol.for('b')] = 'b';
    obj['c'] = 'c';
    obj.d = 'd';
    
    0 讨论(0)
  • 2020-12-04 10:29

    The solution I chose is similar to Daniel's, but rather than use an object factory and override the toString, I explicitly add the hash to the object when it is first requested through a getHashCode function. A little messy, but better for my needs :)

    Function.prototype.getHashCode = (function(id) {
        return function() {
            if (!this.hashCode) {
                this.hashCode = '<hash|#' + (id++) + '>';
            }
            return this.hashCode;
        }
    }(0));
    
    0 讨论(0)
  • 2020-12-04 10:31

    JavaScript objects can only use strings as keys (anything else is converted to a string).

    You could, alternatively, maintain an array which indexes the objects in question, and use its index string as a reference to the object. Something like this:

    var ObjectReference = [];
    ObjectReference.push(obj);
    
    set['ObjectReference.' + ObjectReference.indexOf(obj)] = true;
    

    Obviously it's a little verbose, but you could write a couple of methods that handle it and get and set all willy nilly.

    Edit:

    Your guess is fact -- this is defined behaviour in JavaScript -- specifically a toString conversion occurs meaning that you can can define your own toString function on the object that will be used as the property name. - olliej

    This brings up another interesting point; you can define a toString method on the objects you want to hash, and that can form their hash identifier.

    0 讨论(0)
提交回复
热议问题