Javascript对象中的键只能是string?

jshashtable状态:

如果您的密钥是string或数字,则JavaScript的内置对象提供使用方括号表示的哈希表function:

据我所知,键只是string,(因为数字被强制转换成string)。 我只是想检查一下,并确保以上陈述是错误的(因为键不能是数字)。

ECMA标准是否说明了这一点

或者是实现浏览器特定?

如果您的密钥是string或数字,则JavaScript的内置对象提供使用方括号表示的哈希表function

这似乎是不正确的 – 对象键 总是string可能是string或(因为ECMAScript 2015,又名ECMA-262编辑6)符号。 但是这是一个方括号属性访问不同的主题。

请参阅ECMA-262 ed 3§11.2.1(另请参阅ECMAScript 2017(草稿)。 ):

属性按名称访问,使用点符号:

MemberExpression。 IdentifierName

CallExpression。 IdentifierName

或括号表示法:

MemberExpression [Expression]

CallExpression [Expression]

点符号由以下语法转换解释:

MemberExpression。 IdentifierName

在行为上是相同的

MemberExpression [<identifier-name-string>]

和类似地

CallExpression。 IdentifierName

在行为上是相同的

CallExpression [<identifier-name-string>]

其中<identifier-name-string>是一个string文字,它包含与Unicode 标识符名称一样处理Unicode转义序列后的相同字符序列。

所以当使用点符号时,点之后的位必须符合IdentifierName的条件。 但是当使用方括号时,提供了一个expression式 ,它被评估并parsing为一个string。

简而言之,提供了方括号表示法,以便可以使用expression式访问属性,例如

var y = {}; var x = 'foo'; y[x] = 'foo value'; 

在上面, x被提供在方括号中,所以它被评估,返回string'foo'。 由于此属性在y上不存在,因此将其添加。 然后yfoo属性赋值为'foo value'。

一般而言,方括号中的expression式将被评估,并调用其toString()方法。 这是用作属性名称的值。

在点属性访问方法中,标识符不被评估,所以:

 y.bar = 'bar value'; 

用值bar value创build一个属性bar

如果你想创build一个数字属性,那么:

 y[5] = 5; 

将评估5 ,看它不是一个string,调用(或多或less) Number(5).toString() ,它返回string5 ,用于属性名称。 然后分配值5 ,这是一个数字。

编辑

这个答案是在ECMAScript ed3是最新的时候写的,但事情已经开始了。 请参阅后面的参考资料和MDN

你是正确的键只能是string,数字键,如数组中使用的数字键被强制和存储为string。

 var arr = [true]; arr[0] === true; arr['0'] = false; arr[0] === false; 

ECMAScript规范,第42页: ECMA-262脚本第3版 。

生产PropertyName : NumericLiteral的计算方法如下:

  1. 形成NumericLiteral的值。
  2. 返回ToString(结果(1))。

键总是string。 这意味着你不能使用对象实例的身份作为关键。

在Flash的ActionScript 3中(使用与AS2不同的强运行时types),有一个Dictionary对象使用严格的键相等比较,因此您可以将对象实例本身用作键(以及数字,string等)。

如果你想在JavaScript中做同样的事情,这将是困难的,因为你必须生成自己的唯一对象标识符,并将其附加到你想跟踪的每个对象。 有些人build议在Object类中增加一个原型函数,但是这会不必要地增加每个对象的开销。 在任何情况下,您都希望通过一个函数调用为一个对象提供一个可跟踪的ID,将一个递增的静态数字赋给一个唯一的属性,如“ __objectid__ ”。

然后可以想象使用Add(key,value)方法创build一个类似Dictionary的类,但是它必须将string,数字和对象存储在三个独立的内部哈希中,以确保“3”不会与编号为3或id为3的对象__objectid__方法必须自动将__objectid__分配给任何尚未分配id的对象types的键。 即使如此,除非在JavaScript中我没有注意到某些属性赋值的钩子,否则您将无法使用括号访问字典。

那么,这里是我的答案 – 主要是因为我不满意其他(正确)答案中的引用 – []中的属性名称的expression式总是与string相关联,并且此行为在规范中定义良好 。 因此, 根据对所述报价的解释 ,可以将其视为误导和/或不正确。

但是, 这个引用并不假定x[42]x["42"]是不同的 。 它声明 – 在误导性排除其他原语和细节的情况下 – 在正常属性分辨率下只有string和数字才可用作 “散列键”(真正的属性名称),从这个意义上说,引用是可以certificate的正确的。

这些规则来自标准ECMA-262 ECMAScript语言规范第5版(2009年12月)

从“11.2.1属性访问器”(生产规则略)部分:

生成MemberExpression:MemberExpression [Expression]的计算方法如下:

  1. 让baseReference是评估MemberExpression的结果。
  2. 让baseValue成为GetValue(baseReference)。
  3. 让propertyNameReference是评估Expression的结果。
  4. 让propertyNameValue是GetValue(propertyNameReference)。
  5. 调用CheckObjectCoercible(baseValue)。
  6. 让propertyNameString是ToString(propertyNameValue)。
  7. 如果正在评估的句法生成被包含在严格的模式代码中,那么严格要求是真实的,否则就严格假。
  8. 返回基types值为baseValue,引用名称为propertyNameString,严格模式标志严格的Referencetypes的值。

快乐的编码。

这是一个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 

等等

注意Bene:

  • alert( FunctorRA )显示.toString()不枚举非数字索引
  • FunctorRA是数组“衣服”中的通用对象,
  • 没有直接的. 语法上的等价(即使是stringeval强制)
    请参阅dynamic函数名称在JavaScript? 有关如何:冒号的详细信息,可以embedded到函数名称中,即使它通常是一个分隔符,以语法描述初始值设定项属性,标签, ?:条件expression式)等。类似的问题存在. 要求转义所有语法上重要的JavaScript字符代码,如(){}\n ., …。 对于包含括号的expression式来说, []构造可以有效地做到这一点,总的来说,推测可以将string的评估推迟为Stringtypes的对象。 这类似于事实43.x=243.x=2但如果43被表示为Number by (43).x=243["x"]=2的对象,则不适用。 (certificate: javascript:alert( [ (43).x=2, 43["x"]=2 ] ) javascript:alert(43.x=2) javascript:alert( [ (43).x=2, 43["x"]=2 ] )显示2,2javascript:alert(43.x=2)生成错误。

是的,键可以是数字。 实际上,该规范对对象和数组都使用相同的通用映射函数。

那么你用于密钥的所有东西都会被转换为string,因为哈希函数会将string散列到一个几乎唯一的可以被解释为整数的短字节集合中,因此在线性search期间整数比较是低级别和快速的。对象是散列表)。 您将对象和数组串起来用作关键字。 钥匙的大小可以是无限的。 但要小心,导致javascript对象无序。

昨天和今天,我试图围绕出现在这个领域的问题,我写了这些解决scheme。 第一个是哈希表的自定义实现, http ://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/在那里,所有的一切都是用俗语来解释的。 ..

另一个是升级到第一个,它是一个确定性的JSONstring化,将具有字母顺序属性的对象string化: http : //stamat.wordpress.com/2013/07/03/javascript-object-ordered-property-string化/

一探究竟 :)