Javascript对象中的键只能是字符串?

Pac*_*ier 40 javascript

jshashtable状态:

JavaScript的内置对象使用方括号表示属性提供哈希表功能,前提是您的键是字符串或数字:

据我所知,键只是字符串,(因为数字被强制转换成字符串).我只想检查并确保上面所述的内容是错误的(因为密钥不能是数字).

ECMA标准是否说明了这一点......

或者是特定于浏览器的实现?

Rob*_*obG 32

JavaScript的内置对象使用方括号表示属性提供哈希表功能,前提是键是字符串或数字

这似乎是不正确的 - 对象键 总是字符串可能是字符串或(因为ECMAScript 2015,又名ECMA-262 ed 6)符号.但这是方括号属性访问的另一个主题.

参见ECMA-262 ed3§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>是在将Unicode转义序列作为IdentifierName处理后包含相同字符序列的字符串文字.

因此,当使用点表示法时,点后面的位必须符合IdentifierName的条件.但是当使用方括号时,会提供一个表达式,该表达式将被计算并解析为字符串.

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

var y = {};
var x = 'foo';
y[x] = 'foo value';
Run Code Online (Sandbox Code Playgroud)

在上面,x在方括号中提供,因此它被评估,返回字符串'foo'.由于此属性尚未存在y,因此会添加该属性.然后为foo属性y赋值为'foo value'.

一般而言,评估方括号中的表达式toString()调用其方法.它是用作属性名称的值.

在dot属性访问方法中,不评估标识符,因此:

y.bar = 'bar value';
Run Code Online (Sandbox Code Playgroud)

创建bar具有值的属性bar value.

如果要创建数字属性,则:

y[5] = 5;
Run Code Online (Sandbox Code Playgroud)

将评估5,看到它不是一个字符串,调用(或多或少)Number(5).toString()返回字符串5,用于属性名称.然后5为其分配值,即数字.

编辑

这个答案是在ECMAScript ed3是最新的时候编写的,但事情已经发生了变化.请参阅后面的参考资料和MDN.

  • 好的只是为了确定,每当我们做数组[1]它实际上转换为数组["1"]? (4认同)
  • @Pacerier:很好的总结,这正是我需要快速了解的 (2认同)

Mat*_*y F 9

你是正确的键只能是字符串,并且数字键(例如在数组中使用的数字键)被强制并存储为字符串.

var arr = [true];
arr[0] === true;
arr['0'] = false;
arr[0] === false;
Run Code Online (Sandbox Code Playgroud)

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

生产PropertyName : NumericLiteral评估如下:

  1. 形成NumericLiteral的值.
  2. 返回ToString(Result(1)).

  • 这取自ECMA脚本规范,v3 - 第42页:生产PropertyName:NumericLiteral的计算方法如下:1.形成NumericLiteral的值.2.返回ToString(结果(1)). (2认同)

小智 5

好吧,这是我的答案 \xe2\x80\x94 主要是因为我对其他(正确)答案中的引用不满意\xe2\x80\x94 [ ] 中属性名称的表达式总是被强制转换为字符串,这种行为很好规范中定义。因此,取决于解释相关引文的解释,它可能被视为误导和/或不正确。

\n

然而,引用并不假定 和x[42]x["42"]不同的;它指出\xe2\x80\x94,误导性地排除了其他原语和细节\xe2\x80\x94,在正常属性解析下,只有字符串和数字可用作散列键”(真正的属性名称),从这个意义上说,引用可以说是正确的。

\n

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

\n

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

\n
\n

产生式 MemberExpression : MemberExpression [ Expression ] 的计算如下:

\n
    \n
  1. 令 baseReference 为对 MemberExpression 求值的结果。
  2. \n
  3. 令 baseValue 为 GetValue(baseReference)。
  4. \n
  5. 令 propertyNameReference 为计算 Expression 的结果。
  6. \n
  7. 令 propertyNameValue 为 GetValue(propertyNameReference)。
  8. \n
  9. 调用 CheckObjectCoercible(baseValue)。
  10. \n
  11. 令 propertyNameString 为 ToString(propertyNameValue)。
  12. \n
  13. 如果正在评估的语法产生式包含在严格模式代码中,则令 strict 为 true,否则令\nstrict 为 false。
  14. \n
  15. 返回引用类型的值,其基值为 baseValue,其引用名称为\npropertyNameString,其严格模式标志为 strict。
  16. \n
\n
\n


Tri*_*nko 5

键总是字符串。这意味着您不能使用对象实例的身份作为键。

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

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

然后可以想象使用 Add(key,value) 之类的方法创建一个类似字典的类,但它必须将字符串、数字和对象存储在三个单独的内部散列中,以确保“3”不会与数字 3 或 id 为 3 的对象。 add 方法必须自动将 分配__objectid__给尚未分配 id 的任何类型对象的键。即便如此,您也无法使用方括号访问字典,除非在 JavaScript 中存在一些我不知道的属性分配挂钩。