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
上不存在,因此将其添加。 然后y
的foo
属性赋值为'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
的计算方法如下:
- 形成NumericLiteral的值。
- 返回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]的计算方法如下:
- 让baseReference是评估MemberExpression的结果。
- 让baseValue成为GetValue(baseReference)。
- 让propertyNameReference是评估Expression的结果。
- 让propertyNameValue是GetValue(propertyNameReference)。
- 调用CheckObjectCoercible(baseValue)。
- 让propertyNameString是ToString(propertyNameValue)。
- 如果正在评估的句法生成被包含在严格的模式代码中,那么严格要求是真实的,否则就严格假。
- 返回基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=2
是43.x=2
但如果43被表示为Number by(43).x=2
或43["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,2
但javascript: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化/
一探究竟 :)