Javascript 在WeakMap中禁止将基元类型作为键的技术原因是什么?

Javascript 在WeakMap中禁止将基元类型作为键的技术原因是什么?,javascript,Javascript,该标准是这么说的,毫无疑问,在WeakMap中,基元类型不能用作键;但增加这一限制的技术原因是什么 我想实现一个简单的hash函数,将JS值映射到0-65535,如果使用WeakMap,这将非常简单;不幸的是,我需要散列任何内容(包括符号和字符串),但这是被禁止的,我想知道为什么。WeakMaps设计用于将一个弱引用对象映射到另一个弱引用对象。基本类型(如String、Number等)是强引用的,其设计方式是,当您将String值分配给变量时,它不会将引用分配给源字符串,而是将该值复制到新变量(

该标准是这么说的,毫无疑问,在
WeakMap
中,基元类型不能用作键;但增加这一限制的技术原因是什么


我想实现一个简单的
hash
函数,将JS值映射到0-65535,如果使用
WeakMap
,这将非常简单;不幸的是,我需要散列任何内容(包括符号和字符串),但这是被禁止的,我想知道为什么。

WeakMap
s设计用于将一个弱引用对象映射到另一个弱引用对象。基本类型(如
String
Number
等)是强引用的,其设计方式是,当您将
String
值分配给变量时,它不会将引用分配给源字符串,而是将该值复制到新变量(因此,例如,当您更改源变量时,新变量不会更改)

弱引用对象被设置为垃圾收集。当脚本的任何部分都不使用它时,它将被删除并释放内存。JS中的基元类型是强引用的(值被复制,而不是被引用)因此,垃圾收集器将永远不会触发对该值的删除,也不会触发对映射中的强引用、基本类型键的删除(这与
WeakMap
的整个思想相冲突)


但是,如果您仍然需要将基元值用作WeakMap的键,您可以尝试一些解决方法,例如在某个对象中包装基元值,然后将该对象用作键。

考虑假设函数:

f = (i) => WeakMap([[i,2]]);
我们希望,一旦
i
不再在此映射之外引用,它将从映射中删除。但是,如果我有调用
f(3453)的代码
那么
3453453
的值可能会被解释器无限期引用,因此不会从返回的映射中删除。相反,每次使用object literal
{}
执行代码时,您都会得到一个新对象,因此您可以跟踪它是否可引用


我还希望JavaScript实现对原语类型有许多专用的优化,这可能无法与检查它们是否被引用保持兼容。例如,您可以在没有专用内存位置和对象的情况下对
123
的值进行操作。

您看过帖子吗?@NickParsons:当然,用作键的值类型需要永远保留在
WeakMap
中,直到使用
delete
明确删除为止(原因是即使数据中不再存在数字1234或代码,我仍然可以“重新计算”它…这在对象引用中是不可能的,因为一旦对象无法访问,就无法再次获取它)。我根本看不到不允许它们有什么好处,另一方面,我可以看到一个更通用的
WeakMap
,它可以使用值和引用作为键。我没有检查任何Javascript实现的源代码,但我非常确定字符串(我指的是
x=“嘿,你好吗?”;
not
x=new String(“嘿,你好”);
)不会被复制,因为在像Javascript这样字符串是不可变的语言中,这是没有意义的。我想说,最明智的实现是,例如,使用“短字符串优化”将它们存储在常规垃圾收集对象中用于几个字符的字符串的逻辑,因为它们比指针占用的空间小)。请注意,尽管长字符串是内部垃圾收集对象,但它们仍然是“值类型”,因此它们应该作为键保留在
WeakMap
中,直到显式删除为止(原因是
“a”+“b”==“ab”
因此,即使不再引用
“ab”
字符串,我仍然可以重新计算值)。当然,用作键的值类型需要永远保留在WeakMap中,直到使用delete明确删除为止(原因是,即使数据或代码中不再存在数字1234,我仍然可以“重新计算”它…这在对象引用中是不可能的,因为一旦对象无法访问,就无法再次获取它).是的,但是如果你接受显式删除,那么你的映射就没有什么不好的地方,你可以用基本映射来代替。我现在明白你的观点是,你可能有一个映射结构,它在引用类型上很弱,而在值类型上很强。它看起来太复杂了,而且很容易用两个单独的映射实现,所以我真的不明白为什么是标准的应该授权它的存在。