jshashtable 表示:
JavaScript 的内置对象提供了使用方括号表示法作为属性的哈希表功能,只要您的键是字符串或数字:
据我所知,键只能是字符串(因为数字会被强制转换为字符串)。我只是想确认一下上面所说的是否错误(因为键不能是数字)。
ECMA 标准有没有关于此事的规定?
还是实现是特定于浏览器的?
jshashtable 表示:
JavaScript 的内置对象提供了使用方括号表示法作为属性的哈希表功能,只要您的键是字符串或数字:
据我所知,键只能是字符串(因为数字会被强制转换为字符串)。我只是想确认一下上面所说的是否错误(因为键不能是数字)。
ECMA 标准有没有关于此事的规定?
还是实现是特定于浏览器的?
var y = {};
var x = 'foo';
y[x] = 'foo value';
x
用方括号提供,因此它被计算并返回字符串 'foo'。由于这个属性在 y
上不存在,所以它被添加了进去。然后将 y
的 foo
属性赋值为 'foo value'。toString()
方法。这个值就是作为属性名使用的。y.bar = 'bar value';
创建一个具有值bar value
的属性bar
。
如果您想创建一个数字属性,则:
y[5] = 5;
将评估 5
,发现它不是一个字符串,调用(或多或少地)Number(5).toString()
返回字符串5
,该字符串用于属性名称。然后将其赋值为数字5
。
此答案是在ECMAScript第3版时编写的,但是事情已经发展了。请参阅更高版本的参考和MDN。
CallExpression.Ident
与 CallExpression["Ident"]
相同并不意味着 CallExpression[42]
与 CallExpression["42"]
相同(尽管它们是相同的--而且在规范中有确切的措辞)。 - user166390你是对的。键只能是字符串,数值键如数组中使用的键会被强制转换为字符串并存储。
var arr = [true];
arr[0] === true;
arr['0'] = false;
arr[0] === false;
ECMAScript规范,第42页:ECMA-262 Script 3rd Edition。
PropertyName : NumericLiteral
的产生式按以下方式进行评估:
obj [array]
或类似情况。(那是一条用法规则,而不是语法产生式。) - user166390嗯,这里是我的回答——主要是因为我对其他(正确)答案中的参考资料不满意——方括号内的属性名称表达式始终会被强制转换为字符串,而且这种行为在规范中有明确定义。因此,根据引文的解释不同,它可能被认为是误导和/或不正确。
然而,这句话并没有假设x [42]
和x ["42"]
是不同的;它陈述了——有误导性地排除了其他的基元和细节——只有字符串和数字在正常属性解析下才能作为“哈希键”(实际上是属性名称)可用,在这个意义上,这句话是可以被认为是正确的。
这些规则来自标准 ECMA-262 ECMAScript 语言规范第五版(2009 年 12 月)。
来自“11.2.1 属性访问器”章节(省略生产规则):
生产 MemberExpression: MemberExpression [ Expression ] 的评估方法如下:键总是字符串。这意味着您不能使用对象实例的标识作为键。
在Flash的ActionScript 3中(与AS 2不同,使用强类型运行时),有一个使用严格相等比较键的Dictionary对象,因此您可以使用对象实例本身作为键(以及数字、字符串等)。
如果您想在JavaScript中做同样的事情,那将会很困难,因为您必须生成自己的唯一对象ID并将它们附加到您想要跟踪的每个对象上。有人建议向Object类添加原型函数,但这将不必要地增加每个对象的开销。无论如何,您都需要通过函数调用为对象分配可跟踪的ID,该函数将递增的静态数字分配给唯一属性,例如“__objectid__
”。
那么可以考虑创建一个类似于字典的类,带有Add(key, value)等方法,但它必须将字符串、数字和对象存储在三个不同的内部哈希中,以确保"3"不会与数字3或id为3的对象发生冲突。 如果键的类型为对象且尚未分配id,则add方法必须自动分配__objectid__。 即使完成了所有这些步骤,您也无法使用括号访问字典,除非JavaScript中存在一些用于属性赋值的钩子,我不知道。
functor Array
。在使用 函数式编程 范式时非常有用。javascript:
alert(["Using ",window.navigator.userAgent] );
FunctorRA=[]; f=function(){return f}; g=function(x){return x};
FunctorRA[f]=43;
FunctorRA[g(function(){})]="generic";
FunctorRA[g(g)]="idempotent";
alert(FunctorRA);
for (i in FunctorRA)
alert([ "Functor[ ", i,
"]'s\n\n value is \n\n", FunctorRA[i]].join(""));
显示:
Using ,Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100423
Ubuntu/10.04 (lucid) Firefox/3.6.3
一个空的alert
,然后:
Functor[ function () {
return f;
}]'s
value is
43
等等。
须知:
alert( FunctorRA )
显示 .toString()
不会枚举非数字索引FunctorRA
是数组 "衣服" 中的通用对象.
语法等效项(即使使用字符串 eval
强制转换)。有关如何嵌入函数名称中的冒号的详细信息,请参见JavaScript 中的动态函数名称,即使它通常是分隔符以语法上划分初始化器属性、标签、?:
(条件表达式)等。类似的问题也存在于 .
中,需要转义所有语法上重要的 JavaScript 字符代码,例如 (){}\n .,
等。 []
构造有效地为括号内包含的表达式执行此操作,整体上,可能通过延迟将字符串评估为 String 类型的对象来实现。这类似于事实 43.x=2
是被禁止的,但如果 43 被表示为 Number 类型的对象,则 (43).x=2
或 43["x"]=2
则不会出错。
(证明:javascript:alert( [ (43).x=2, 43["x"]=2 ] )
显示 2,2
,但 javascript:alert(43.x=2)
会生成错误)。 { "1": true }[1] // true
Map
或Set
将是更好的选择,特别是因为它们保证O(1)的查找时间。是的,键可以是数字。实际上,规范为对象和数组都使用相同的通用映射函数。
好的,由于哈希函数将字符串哈希成一个几乎唯一的字节集合,可以将其解释为整数,并且线性搜索期间使用整数比较是低级别和快速的,因此您用于关键字的所有内容都会被转换为字符串(JavaScript对象是哈希表)。您可以将对象和数组字符串化以将它们用作关键字。关键字的大小可以无限制地增长。但要注意,因为JavaScript对象是无序的。
昨天和今天,我一直在努力理解这个领域中出现的问题,并写下了这些解决方案。第一个是哈希表的自定义实现,JavaScript使用对象作为关键字。在那里,一切都以通俗易懂的方式解释...
另一个是对第一个的升级,它是一个确定性JSON字符串化,可以按字母顺序排列属性字符串化对象:JavaScript确定性对象字符串化
来看看吧 :)