解决方法:使用对象作为键的JavaScript字典

14

我阅读了一些关于JavaScript字典实现的问题和答案,但它们不符合我的要求:

  • 该字典必须能够使用对象作为键
  • 值必须可通过[]运算符进行访问

因此,我想到了覆盖Object.prototype中的valueOf方法,如下所示:

Object.__id__ = 0;
Object.prototype.valueOf = function() {
   if(!this.__id__)
      this.__id__ = ++Object.__id__;
    return "__id__" + this.__id__;
}
Object.prototype.toString = Object.prototype.valueOf;

//test   
var x = {p1: "5"};
var y = [6];
var z = {};
z[x] = "7";
z[y] = "8";
console.log(z[x], z[y]);

我在谷歌浏览器中测试了这个方法,似乎很有效,但是我有点怀疑,因为它实现得太容易了,是否会带来一些缺点。

考虑到整个代码中没有其他用途使用 valueOf 方法,你认为有没有任何不利之处?

3个回答

6

这是一个有趣的想法。我建议使用我的jshashtable库。它满足你的第一个要求,但不满足第二个。我并没有真正看到坚持使用方括号属性访问符号的优势:你有特定的要求吗?

使用jshashtable,你可以向Hashtable构造函数提供一个哈希函数。该函数将传入一个作为键使用的对象,并必须返回一个字符串;你可以使用一个与你现在使用的函数类似的函数,而无需触及Object.prototype

你的想法存在一些缺点:

  1. 你的valueOf方法会在任何本地对象的for...in循环中显示;
  2. 你没有确定哪些键应该被视为相等的方法,这可能是你想要做的事情。相反,所有键都将被视为唯一的。
  3. 这不能用于主机对象(即由环境提供的对象,例如DOM元素)

我以前经常使用你的库,效果很好。但是现在我正在开发一个将ActionScript 3转换为Javascript的转换器。AS3提供了一个Dictionary。如果我使用你的库,我需要检查类型并替换括号为get/set。如果我使用Object,则valueOf不会出现在for...in中,但如果我定义一个新的“类”,则会出现(可能在其他浏览器中会有不同的行为)。由于我不想覆盖Object.prototype.valueOf本身,你回答了我的问题。 - fishbone

1

这是一个有趣的问题,因为我迄今为止一直认为任何对象都可以用作索引(但从未尝试过与关联数组)。我对 JavaScript 的内部工作原理了解不够,但我敢打赌 valueOf 在 JavaScript 中的某个地方被使用了,即使不在你的代码中。你可能会遇到看似无法解释的问题。至少,我会限制自己使用一个新类并离开 Object;或者,你可以显式调用哈希函数,将其称为 myHash() 或其他名称,并调用 z[x.myHash()],这样会增加混乱,但让我个人感觉更好。我无法抗拒认为有一个更加了解 JavaScript 的解决方案,所以请考虑所有这些丑陋的解决方法 ;)


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接