散列JavaScript对象

时间:2014-01-24 21:24:16

标签: javascript hash

我有一个函数接收JS对象列表作为参数。我需要将有关这些对象的信息存储在私有变量中以供将来参考。我不想将属性填充到对象本身,我只是想在字典中将其保留在带外。我需要能够在子线性时间内查找对象的元数据。

为此我需要一个hash函数,对于任何两个对象o1o2

每当hash(o1) !== hash(o2)

o1 !== o2

这种哈希函数的一个完美例子是对象的内存地址,但我不认为JS会公开它。有办法吗?

4 个答案:

答案 0 :(得分:2)

每个对象引用都不同。为什么不把对象推到数组上?遍历查找对象引用的数组可能仍然比检查递归庄园中的每个对象以生成哈希键更好。

function Dictionary() {
    var values = [];

    function contains(x) {
        var i = values.length;

        while(i--) {
            if (values[i] === x) {
                return true;
            }
        }

        return false;
    }

    function count() {
        return values.length;
    }

    function get(i) {
        return (i >= 0 && i < values.length) ? values[i] : null;
    }

    function set(o) {
        if (contains(o)) {
            throw new Error("Object already exists in the Dictionary");
        }
        else {
            return values.push(o) - 1;
        }
    }

    function forEach(callback, context) {
        for (var i = 0, length = values.length; i < length; i++) {
            if (callback.call(context, values[i], i, values) === false) {
                break;
            }
        }
    }

    return {
        get: get,
        set: set,
        contains: contains,
        forEach: forEach,
        count: count
    };
}

使用它:

var objects = Dictionary();

var key = objects.set({});

var o = objects.get(key);

objects.contains(key); // returns true

objects.forEach(function(obj, key, values) {
    // do stuff
}, this);

objects.count(); // returns 1

objects.set(o); // throws an error

答案 1 :(得分:2)

要存储有关对象的元数据,您可以使用WeakMap

  

WeakMaps是键/值映射,其中键是对象。


请注意,此API仍处于试验阶段,因此尚未得到广泛支持(请参阅support table)。有polyfill implementation使用defineProperty设置GUID(详见here)。

答案 2 :(得分:1)

Javascript不提供对内存的直接访问(或者对文件系统提供直接访问)。

您可能只想在分析(哈希)函数中创建属性/变量,然后将它们返回到调用函数的位置以进行存储/持久化以供以后参考。

答案 3 :(得分:0)

感谢所有插话回复的人。大家都说服我,我想做的事情目前在JavaScript中无法实现。

似乎有两个基本的妥协,这个用例的人可以选择:

  1. 使用===

    进行线性搜索

    ===似乎是区分具有不同引用的两个具有相同值的对象的唯一内置方法。 (如果您有两个对象o1o2,并进行了深入比较并发现它们的值相同,您可能仍然想知道它们是否是引用相同的。除了{{ 1}}你可以做一些奇怪的事情,例如向===添加一个属性,看看是否出现在o1中。

  2. 向对象添加属性。

    我不喜欢这种方法,因为我没有充分的理由将这些信息暴露给外界。然而,一位同事告诉我一个我不知道的功能:Object.defineProperty.有了这个,我可以减轻我的主要担忧:首先,我的id会在对象枚举期间显示,不需要,以及第二,如果存在命名空间冲突,有人可能会无意中改变我的身份。

  3. 所以,如果有人来这里想要我想要的相同的东西,我会把它放在那里,以便我将使用Object.defineProperty添加一个唯一的id。

相关问题