如何在 JavaScript 中进行关联数组/散列

IT技术 javascript dictionary hashtable
2021-01-26 13:24:01

我需要像在 C# 中那样使用 JavaScript 存储一些统计信息:

Dictionary<string, int> statistics;

statistics["Foo"] = 10;
statistics["Goo"] = statistics["Goo"] + 1;
statistics.Add("Zoo", 1);

JavaScript 中是否有Hashtable类似的东西Dictionary<TKey, TValue>
我怎么能以这种方式存储值?

6个回答

使用JavaScript 对象作为关联数组

关联数组:简单来说,关联数组使用字符串而不是整数作为索引。

创建一个对象

var dictionary = {};

JavaScript 允许您使用以下语法向对象添加属性:

Object.yourProperty = value;

相同的替代语法是:

Object["yourProperty"] = value;

如果可以,还可以使用以下语法创建键值对象映射:

var point = { x:3, y:2 };

point["x"] // returns 3
point.y // returns 2

您可以使用 for..in 循环构造遍历关联数组,如下所示

for(var key in Object.keys(dict)){
  var value = dict[key];
  /* use key/value for intended purpose */
}
失败。JavaScript 不支持将对象引用作为键,而像 Flash/AS3 Dictionary 这样的东西支持。在 JavaScript 中,var obj1 = {}; var obj2 = {}; var table= {}; table[obj1] = "A"; table[obj2] = "B"; alert(table[obj1]); //displays B, 因为它无法区分键 obj1 和 obj2;它们都被转换为字符串,只是变成了“对象”之类的东西。完全失败,并且在 JavaScript 中使用完整的引用和循环引用使类型安全的序列化变得困难或性能不佳。在 Flash/AS3 中很容易。
2021-03-22 13:24:01
@Leo console.log({A:'B',C:'D'}[foo]) 应该给你 A B。
2021-04-01 13:24:01
@Leo 这个例子似乎是错误的。for... in因为字典会遍历它的键,所以Object.keys在那里似乎放错了地方。Object.keys返回字典键的数组,for... in对于数组,循环遍历 它的“键”,对于数组,键是它的索引,而不是它的值。
2021-04-01 13:24:01
请注意,作者用 初始化“关联数组”的方法new Array()是不赞成的。这篇文章最终提到了它的缺点并提出了建议new Object(){}作为首选替代方案,但这已经接近尾声,我担心大多数读者不会走那么远。
2021-04-04 13:24:01
好吧,在 JS 中,我们可以通过检查相等性或通过以下方式定义equals方法来验证的唯一方法Point.prototype.equals = function(obj) { return (obj instanceof Point) && (obj.x === this.x) && (obj.y === this.y); };
2021-04-06 13:24:01
var associativeArray = {};
associativeArray["one"] = "First";
associativeArray["two"] = "Second";
associativeArray["three"] = "Third";

如果您来自面向对象的语言,您应该查看这篇文章

你也可以用更少的行来做到这一点: var associativeArray = {"one" : "First", "two" : "second", "three" : "Third"}; 然后 associativeArray["one"] 返回“First”,assocativeArray["four"] 返回 null。
2021-03-18 13:24:01

所有现代浏览器都支持 JavaScript Map对象。使用 Map 比使用 Object 更好的原因有两个:

  • 一个对象有一个原型,所以地图中有默认的键。
  • 对象的键是字符串,它们可以是 Map 的任何值。
  • 当您必须跟踪对象的大小时,您可以轻松获得地图的大小。

例子:

var myMap = new Map();

var keyObj = {},
    keyFunc = function () {},
    keyString = "a string";

myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

myMap.size; // 3

myMap.get(keyString);    // "value associated with 'a string'"
myMap.get(keyObj);       // "value associated with keyObj"
myMap.get(keyFunc);      // "value associated with keyFunc"

如果您希望未从其他对象引用的键被垃圾收集,请考虑使用WeakMap而不是 Map。

Map当您的键是一个对象但应该按值而不是引用进行比较时,几乎没有用。
2021-03-12 13:24:01
@CameronLee 肯定会
2021-03-21 13:24:01
在撰写此答案一年多之后,“所有现代浏览器都支持 Map”的说法仍然不正确。只有在桌面上,您才能至少获得基本的地图支持。不在移动设备上。例如,Android 浏览器根本不支持地图。即使在桌面上,一些实现也是不完整的。例如,IE11 仍然不支持通过“for...of...”进行枚举,因此如果您想要 IE 兼容性,则必须使用令人厌恶的 .forEach 组合。此外,JSON.stringify() 不适用于我尝试过的任何浏览器中的 Map。此外,初始值设定项在 IE 或 Safari 中不起作用。
2021-03-22 13:24:01
希望在几年后,这将是投票最多的答案。
2021-03-26 13:24:01
有出色的浏览器支持。再检查一遍。无论如何,这很容易填充,因此原生浏览器支持不是问题。
2021-04-05 13:24:01

除非您有特定的理由不这样做,否则只需使用普通对象。可以使用哈希表样式的语法引用 JavaScript 中的对象属性:

var hashtable = {};
hashtable.foo = "bar";
hashtable['bar'] = "foo";

两个foobar元素,现在则引用如下:

hashtable['foo'];
hashtable['bar'];

// Or
hashtable.foo;
hashtable.bar;

当然,这确实意味着您的密钥必须是字符串。如果它们不是字符串,它们会在内部转换为字符串,因此它可能仍然有效。你的旅费可能会改变。

请注意,对象不能用作JavaScript 中的好吧,它们可以,但是它们被转换为它们的字符串表示形式,因此任何对象最终都将成为完全相同的键。请参阅下面的@TimDown 的 jshashtable 建议。
2021-03-21 13:24:01
这个例子令人困惑,因为您在两个实例中都使用 foo 和 bar 作为键和值。更清楚地表明var dict = {}; dict.key1 = "val1"; dict["key2"] = "val2";dict 的 key1 元素可以被dict["key1"]等效地引用dict.key1
2021-03-29 13:24:01
Jonas:请记住,当设置属性时,您的整数将转换为字符串:var hash = {}; hash[1] = "foo"; alert(hash["1"]);警报“foo”。
2021-03-31 13:24:01
作为整数的键没有给我带来任何问题。stackoverflow.com/questions/2380019/...
2021-04-02 13:24:01
如果您的密钥之一是“ proto ”或“ parent ”怎么办?
2021-04-11 13:24:01

由于 JavaScript 中的每个对象都表现得像 - 并且通常被实现为 - 一个哈希表,我只是同意......

var hashSweetHashTable = {};
我迟到了 9 年(我对编程一无所知,更不用说当时的这个网站了),但是......在地图上的某个点?在这种情况下,您最好为此使用 HashTable,通过坐标(对象,而不是字符串查找
2021-03-17 13:24:01
被否决是因为它没有显示如何实际访问“哈希表”中的值。
2021-03-19 13:24:01
@MikeWarrenif (hashSweetHashTable.foo)应该输入 if 块 iffoo已设置。
2021-04-04 13:24:01