节点:如何将对象作为哈希对象的键?

时间:2018-08-31 14:54:03

标签: javascript node.js

请查看以下代码段:

class Node {
    constructor(num) {
        this.num = num;
        this.right = null;
        this.left = null;
    }
}

let node1 = new Node(1);
let node2 = new Node(2);
let hash = {};
hash[node1] = 1;
console.log(hash[node2]);  // prints "1" ????

为什么hash [node2]返回值1? 哈希中仅存储了node1 ...

3 个答案:

答案 0 :(得分:3)

如果您记录对象,则会得到以下信息:

{ '[object Object]': 1 }

为什么下面的记录为1,因为node2被解释为[object Object]

console.log(hash[node2]); //This is evaluating hash['object Object'] (Again)

要解决此问题,有多种方法,一种方法是使用JSON API对对象进行字符串化,然后将返回值用作键。

例如

hash[JSON.stringify(node1)] = 1;

现在您拥有的是:

{'{"num":1,"right":null,"left":null}': 1 }

因此,按预期方式,现在将无法访问hash [node2]。

hash[node2] === undefined; //true
hash[JSON.stringify(node2)] === undefined; //true

您可能想为此创建一个小的API。作为一个非常粗糙的例子:

class Hash {

    constructor () {
        this.hashes = {};
    }

    get (key) {
        return this.hashes[JSON.stringify(key)];
    }

    set (key, value) {
        this.hashes[JSON.stringify(key)] = value;
    }
}

const hashStore = new Hash();

hashStore.set({foo: 'bar'}, 1);

hashStore.set({foo: 'cheese'}, 2);

console.log(hashStore.get({foo: 'bar'})); // 1
console.log(hashStore.get({foo: 'cheese'})); //2

或者,如果您仅使用对象作为“您的控制”中的键,那么正如Jakub Keller在其答案中指出的那样,您可以覆盖Node类的toString函数。

这两种方法的后遗症都是“唯一性”,要使这两种方法成为稳定的方法,您都希望为每个对象引入一个唯一键,如果您使用Jakub Keller的方法,则应使用该唯一键在toString重写中。

这两种方法都可以满足一组需求,如果您要存储文字,作为键的一组不同对象,我可能会采用我的方法,并让API在存储的每个对象上写入一个自定义的唯一ID在get方法中,它还是不完美的,因为您可能会覆盖现有密钥。

答案 1 :(得分:2)

该值显示为1,因为任何一个对象的哈希在技术上都是[object Object]。因此,您的密钥是[object Object]

尝试覆盖Node类的toString并通过调用toString进行显式转换:

class Node {
    constructor(num) {
        this.num = num;
        this.right = null;
        this.left = null;
    }

    toString() {
        return this.num;
    }
}

let node1 = new Node(1);
let node2 = new Node(2);
let hash = {};
hash[node1] = 1;
console.log(hash[node2.toString()]);
// output: 2

答案 2 :(得分:0)

您可以像这样在哈希对象上使用Object.assign()方法:

hash = Object.assign({node1, node2}, {});