this answer年第3次更新中所述,此符号:

var hash = {};
hash[X]

不会实际散列对象X;它实际上只是将X转换成一个字符串(如果它是一个对象,则通过.toString(),或其他各种基本类型的内置转换),然后在"hash"中查找该字符串,而不进行散列.对象相等性也不会被判断——如果两个不同的对象具有相同的字符串转换,它们只会相互覆盖.

考虑到这一点,JavaScript中是否有任何高效的hashmaps实现?

(例如,第二个Google结果为javascript hashmap,对于任何操作都会产生一个O(n)的实现.其他各种结果忽略了一个事实,即具有等效字符串表示的不同对象会相互覆盖.

推荐答案

手动散列对象,并将生成的字符串用作常规JavaScript字典的键.毕竟,你最有资格知道是什么让你的物品独一无二.我就是这么做的.

例子:

var key = function(obj){
  // Some unique object-dependent key
  return obj.totallyUniqueEmployeeIdKey; // Just an example
};

var dict = {};

dict[key(obj1)] = obj1;
dict[key(obj2)] = obj2;

通过这种方式,您可以控制JavaScript执行的索引,而无需进行繁重的内存分配和溢出处理.

当然,如果你真的想要"工业级的解决方案",你可以构建一个由关键函数参数化的类,并使用容器的所有必要API,但是……我们使用JavaScript,并试图简单和轻量级,所以这个功能解决方案简单而快速.

密钥函数可以像 Select 对象的正确属性一样简单,例如已经是唯一的密钥或一组密钥、一起是唯一的密钥的组合,或者像使用诸如在DojoX encodingDojoX UUID中的一些密码散列一样复杂.虽然后一种解决方案可能会产生唯一的键,但就我个人而言,我会不惜一切代价避免它们,特别是在我知道是什么让我的对象具有唯一性的情况下.

2008年,这个简单的解决方案仍然需要更多的解释.让我在问答中澄清一下这个 idea ;一张表格.

Your solution doesn't have a real hash. Where is it???

JavaScript是一种高级语言.它的基本原语(Object)包括一个哈希表来保存属性.为了提高效率,此哈希表通常使用低级语言编写.使用带有字符串键的简单对象,我们可以使用一个高效实现的哈希表,而无需我们的任何努力.

How do you know they use a hash?

有三种主要方法可以保持对象集合可通过键寻址:

  • 无序的.在这种情况下,要通过关键点检索对象,我们必须判断所有关键点,在找到它时停止.平均而言,需要n/2个比较.
  • 命令.
  • 哈希表.平均而言,它需要一个恒定的时间.比较:O(n)与O(logn)与O(1).繁荣

显然,JavaScript对象使用某种形式的哈希表来处理一般情况.

Do browser vendors really use hash tables???

真正地

  • Chrome/node.js/V8:
  • Firefox/Gecko:

Do they handle collisions?

是.请参见上文.如果您发现不相等字符串上的冲突,请毫不犹豫地向供应商提交bug.

So what is your idea?

如果你想散列一个对象,找出它的唯一性,并将其用作密钥.不要试图计算真正的哈希或模拟哈希表——它已经被底层JavaScript对象有效地处理了.

在JavaScript的Object中使用此键可以利用其内置的哈希表,同时避免可能与默认属性发生冲突.

让你开始的例子:

  • 如果对象包含唯一的用户名,请将其用作密钥.
  • 如果包含唯一的客户编号,请将其用作密钥.
  • 如果字段组合是唯一的-将其用作关键字.
    • 美国州缩写+驾照号码是很好的密钥.
    • 国家缩写+Passport 号码也是不错的 keys .
  • 字段或整个对象上的某些函数可以返回唯一的值——将其用作键.

I used your suggestion and cached all objects using a user name. But some wise guy is named "toString", which is a built-in property! What should I do now?

显然,如果结果键完全由拉丁字符组成的可能性微乎其微,那么您应该对此采取一些措施.例如,在开头或结尾添加您喜欢的任何非拉丁Unicode字符,以取消与默认属性"#toString"、"#MarySmith"的冲突.如果使用复合键,则使用某种非拉丁定界符"name、city、state"分隔键组件.

一般来说,在这里,我们必须有创意, Select 具有给定限制(唯一性、与默认属性的潜在冲突)的最简单关键点.

注意:根据定义,唯一键不会发生冲突,而潜在的哈希冲突将由底层Object处理.

Why don't you like industrial solutions?

依我看,最好的代码是完全没有代码:它没有错误,不需要维护,易于理解,并且可以即时执行.我看到的所有"JavaScript哈希表"都是>;dict[key] = value行代码,涉及多个对象.比较一下:dict[key] = value.

另一点是:使用JavaScript和完全相同的原始对象来实现已经实现的东西,有没有可能超越用低级语言编写的原始对象的性能呢?

I still want to hash my objects without any keys!

我们很幸运:ECMAScript 6(2015年6月发布)定义了mapset.

根据定义判断,他们可以使用对象的地址作为密钥,这使得对象在没有人工密钥的情况下立即变得不同.两个不同但完全相同的对象OTOH将被映射为不同的对象.

MDN分比较:

对象与贴图的相似之处在于,它们都可以将关键点设置为值,

  • 对象的键是字符串和符号,而它们可以是 map 的任何值,包括函数、对象和任何基本体.
  • 贴图中的键是有序的,而添加到对象中的键不是有序的.因此,当对其进行迭代时,Map对象将按
  • 使用size属性可以轻松获得贴图的大小,而对象中属性的数量必须手动确定.
  • 映射是一个iterable,因此可以直接迭代,而在对象上迭代需要以某种方式获取其键
  • 一个对象有一个原型,所以如果你不小心的话, map 中的默认关键点可能会与你的关键点发生碰撞.从ES5开始,这可以
  • 在涉及频繁添加和删除密钥对的场景中,映射可能执行得更好.

Javascript相关问答推荐

如何在Javascript中的控制台上以一行形式打印循环的结果

用JavaScript复制C#CRC 32生成器

我在我的Java代码中遇到了问题,代码的一部分看不到先前定义的对象

如何解决useState错误—setSelect Image不是函数''

如何使onPaste事件与可拖动的HTML元素一起工作?

在执行异步导入之前判断模块是否已导入()

我可以使用空手道用户界面来获取网页的当前滚动位置吗?

WP Bootstrap NavWaker:下拉菜单一次打开所有下拉菜单

当用户点击保存按钮时,如何实现任务的更改?

使用NextJS+MongoDB+Prisma ORM获取无效请求正文,无法发布错误

如何在FastAPI中为通过file:/URL加载的本地HTML文件启用CORS?

如何使用基于promise (非事件emits 器)的方法来传输数据?

第一项杀死下一项,直到数组长度在javascript中等于1

使用Document.Evaluate() Select 一个包含撇号的HTML元素

将Auth0用户对象存储在nextjs类型脚本的Reaction上下文中

有没有办法通过使用不同数组中的值进行排序

限制数组中每个元素的长度,

Firebase函数中的FireStore WHERE子句无法执行

如何用react组件替换dom元素?

鼠标进入,每秒将图像大小减小5%