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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6066846/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 20:06:26  来源:igfitidea点击:

Keys in Javascript objects can only be strings?

javascript

提问by Pacerier

jshashtable states:

jshashtable 指出:

JavaScript's built-in objects do provide hashtable functionality using the square brackets notation for properties, provided your keys are strings or numbers:

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

From what I know, keys are only strings, (since numbers are coerced into strings anyway). I just want to check and be sure that what is stated above is false (since keys can't be numbers).

据我所知,键只是字符串,(因为无论如何数字都被强制转换为字符串)。我只是想检查并确保上面所说的是错误的(因为键不能是数字)。

Did ECMA standard stated anything about this..

ECMA 标准是否对此有任何说明..

Or is the implementation browser-specific?

还是特定于浏览器的实现?

采纳答案by RobG

JavaScript's built-in objects do provide hashtable functionality using the square brackets notation for properties, provided your keys are strings or numbers

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

That seems to be incorrect - object keysare always stringsmay be strings or (since ECMAScript 2015, aka ECMA-262 ed 6) symbols. But that is a different topic to square bracket property access.

这似乎是不正确的 -对象键总是字符串,可能是字符串或(自 ECMAScript 2015 起,又名 ECMA-262 ed 6)符号。但这与方括号属性访问是不同的主题。

See ECMA-262 ed 3 § 11.2.1 (Please also see ECMAScript 2017 (draft).):

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

Properties are accessed by name, using either the dot notation:

MemberExpression . IdentifierName

CallExpression . IdentifierName

or the bracket notation:

MemberExpression [ Expression ]

CallExpression [ Expression ]

The dot notation is explained by the following syntactic conversion:

MemberExpression . IdentifierName

is identical in its behaviour to

MemberExpression [ <identifier-name-string> ]

and similarly

CallExpression . IdentifierName

is identical in its behaviour to

CallExpression [ <identifier-name-string> ]

where <identifier-name-string>is a string literal containing the same sequence of characters after processing of Unicode escape sequences as the IdentifierName.

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

成员表达式。标识符名称

调用表达式。标识符名称

或括号符号:

成员表达式 [ 表达式 ]

CallExpression [ 表达式 ]

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

成员表达式。标识符名称

其行为与

MemberExpression [ <identifier-name-string> ]

同样

调用表达式。标识符名称

其行为与

CallExpression [ <identifier-name-string> ]

其中<identifier-name-string>是一个字符串文字,在处理 Unicode 转义序列后包含与 IdentifierName 相同的字符序列。

So when using dot notation, the bit after the dot must fit the criteria for an IdentifierName. But when using square brackets, an expressionis provided that is evaluated and resolved to a string.

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

Briefly, square bracket notation is provided so that properties can be accessed using an expression, e.g.

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

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

In the above, xis provided in square brackets so it is evaluated, returning the string 'foo'. Since this property doesn't exist on yyet, it is added. The fooproperty of yis then assigned a value of 'foo value'.

在上面,x在方括号中提供,因此它被评估,返回字符串'foo'。由于此属性尚不存在y,因此已添加。然后将的foo属性y赋值为“foo value”。

In general terms, the expressionin the square brackets is evaluated and its toString()method called. It is that value that is used as the property name.

一般而言,方括号中的表达式会被计算并toString()调用其方法。正是该值用作属性名称。

In the dot property access method, the identifier is not evaluated, so:

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

y.bar = 'bar value';

creates a property barwith a value bar value.

创建bar一个值为的属性bar value

If you want to create a numeric property, then:

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

y[5] = 5;

will evaluate 5, see it's not a string, call (more or less) Number(5).toString()which returns the string 5, which is used for the property name. It is then assigned the value 5, which is a number.

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

Edit

编辑

This answer was written when ECMAScript ed3 was current, however things have moved on. Please see later references and MDN.

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

回答by Matty F

You're right keys can only be strings, and numeric keys such as those used in Arrays are coerced and stored as strings.

你是对的键只能是字符串,而数组中使用的数字键被强制并存储为字符串。

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

ECMAScript spec, page 42: ECMA-262 Script 3rd Edition.

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

The production PropertyName : NumericLiteralis evaluated as follows:

生产PropertyName : NumericLiteral评估如下:

  1. Form the value of the NumericLiteral.
  2. Return ToString(Result(1)).
  1. 形成 NumericLiteral 的值。
  2. 返回到字符串(结果(1))。

回答by Triynko

The keys are always strings. This means you can't use an object instance's identity as a key.

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

In Flash's ActionScript 3 (uses strong run-time types unlike AS2) there is a Dictionary object which uses strict equality comparison for keys, so that you can use object instances themselves as keys (as well as numbers, strings, etc.).

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

If you wanted to do the same thing in JavaScript, it would be difficult, because you'd have to generate your own unique object ids and attach them to every object you wanted to track. Some have suggested adding a prototype function to the Object class, but that would add overhead to every object unnecessarily. In any case, you'd want to give an object a trackable ID via a function call that assigns an incrementing static number to a unique property such as "__objectid__".

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

It would then be conceivable to create a Dictionary-like class with methods like Add(key,value), but it would have to store strings, numbers, and objects in three separate internal hashes to ensure "3" doesn't collide with the number 3 or the object with id 3. The add method would have to automatically assigned an __objectid__to any key of type object that didn't already have an id assigned. Even after all that, you wouldn't be able to access the dictionary using brackets, unless there are some hooks for property assignments that I'm not aware of in JavaScript.

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

回答by Triynko

Well, here is my answer -- mostly because I was not satisfied with the references in the other (correct) answers -- expressions for property names in [ ] are always coereced to stringsand this behavior is well definedin the specification. Thus, depending upon interpretationof the quote in question, it can be taken as misleading and/or incorrect.

好吧,这是我的答案——主要是因为我对其他(正确)答案中的引用不满意—— [] 中属性名称的表达式总是被强制转换为字符串,并且这种行为在规范中得到了很好的定义。因此,根据对相关引用的解释,它可能被视为误导和/或不正确。

However, the quote does not presume that x[42]and x["42"]are different; it states -- with the misleading exclusion of other primitives and details -- that only strings and numbers are usableas "hash keys" (really property names) under normal property resolution and, in this sense, the quote is arguably correct.

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

These rules are from Standard ECMA-262 ECMAScript Language Specification 5th edition (December 2009)

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

From section "11.2.1 Property Accessors" (production rules omitted):

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

The production MemberExpression : MemberExpression [ Expression ] is evaluated as follows:

  1. Let baseReference be the result of evaluating MemberExpression.
  2. Let baseValue be GetValue(baseReference).
  3. Let propertyNameReference be the result of evaluating Expression.
  4. Let propertyNameValue be GetValue(propertyNameReference).
  5. Call CheckObjectCoercible(baseValue).
  6. Let propertyNameString be ToString(propertyNameValue).
  7. If the syntactic production that is being evaluated is contained in strict mode code, let strict be true, else let strict be false.
  8. Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict.

产生式 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. 如果正在评估的语法产生式包含在严格模式代码中,则让 strict 为真,否则让 strict 为假。
  8. 返回一个 Reference 类型的值,其基值为 baseValue,引用名称为 propertyNameString,其严格模式标志为严格。

Happy coding.

快乐编码。

回答by Ekim

Here is a functor Array. It is useful when using a Functional Programming paradigm.

这是一个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(""));

displays:

显示:

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

an empty alertand then:

一个空alert然后:

Functor[ function () {
    return f;
}]'s

 value is 

43

etc.

等等。

Note Bene:

注意本:

  • alert( FunctorRA )shows .toString()does not enumerate non-numeric indexes
  • FunctorRAis a generic object in array's "clothing"
  • there is no direct .syntactic equivalent ( even with string evalcoercion )
    see Dynamic function name in javascript?for details on how :, a colon, can be embedded in a function name even though it is usually a delimiter to syntactically delineate initializer properties, labels, ?:(conditional expressions) etc. An analogous problem exists with .requiring the escaping of all syntactically significant JavaScript character codes such as (){}\n .,... . The []construct effectively does this for the parenthetically contained expression, as a whole, presumably by deferring the evaluation of the string to be an object of type String. This is similar to the fact 43.x=2is verboten but not if 43 is represented as an object of type Number by (43).x=2or 43["x"]=2. (proof: javascript:alert( [ (43).x=2, 43["x"]=2 ] )displays 2,2but javascript:alert(43.x=2)generates an error).
  • alert( FunctorRA )显示.toString()不枚举非数字索引
  • FunctorRA是数组“服装”中的通用对象
  • 没有直接的.语法等价物(即使使用字符串eval强制)在 javascript 中
    看到动态函数名称?有关如何:将冒号嵌入到函数名称中的详细信息,即使它通常是语法上描述初始化器属性、标签、?:(条件表达式)等的分隔符。.需要转义所有语法上重要的 JavaScript 字符存在类似的问题代码如(){}\n .,.... 该[]构造有效地为括号内包含的整个表达式执行此操作,大概是通过将字符串的评估推迟为 String 类型的对象。这与事实相似43.x=2是禁止的但如果43被表示为通过Number类型的对象(43).x=243["x"]=2。(证明:javascript:alert( [ (43).x=2, 43["x"]=2 ] )显示2,2javascript:alert(43.x=2)产生错误)。

回答by stamat

Well everything that you use for the key is converted to string because of hashing function that hashes strings to a nearly unique short set of bytes that can be interpreted as an integer, cause integer comparison during the linear search is low level and fast.(JavaScript objects are hash tables). You stringify objects and arrays to use them as a key. Keys can be unlimited in size. But beware, cause javascript objects are unordered.

好吧,您用于键的所有内容都被转换为字符串,因为散列函数将字符串散列到几乎唯一的短字节集,可以解释为整数,导致线性搜索期间的整数比较是低级和快速的。(JavaScript对象是哈希表)。您将对象和数组字符串化以将它们用作键。密钥的大小可以不受限制。但要注意,因为 javascript 对象是无序的。

Yesterday and today, I've tried to wrap my head around the problems appearing in this domain and I've written these solutions. First one is a custom implementation of a hash table, http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/And there everything is explained in laymans terms...

昨天和今天,我试图解决这个领域中出现的问题,并编写了这些解决方案。第一个是哈希表的自定义实现,http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/ 一切都用外行术语解释。 ..

other one is an upgrade to the first one, and it is a deterministic JSON stringify, that stringifies objects with alphabetically ordered properties: http://stamat.wordpress.com/2013/07/03/javascript-object-ordered-property-stringify/

另一个是对第一个的升级,它是一个确定性的 JSON 字符串化,它使用按字母顺序排列的属性对对象进行字符串化:http: //stamat.wordpress.com/2013/07/03/javascript-object-ordered-property-字符串化/

Check it out :)

一探究竟 :)

回答by Jonas Wilms

JavaScript's built-in objects do provide hashtable functionality ...

JavaScript 的内置对象确实提供了哈希表功能......

Yes, kind of. Objects are by definition just a collection of key-value pairs (whereas keys are strings or Symbols). However as they are used like lookup tables by a lot of people, most engines will choose a hashtable like datastructure for implementing objects internally (in some cases). So yes, you can use objects as a hashtable (but it is not guaranteed that the engine will actually use a hashtable under the hood).

是的,有点。根据定义,对象只是键值对的集合(而键是字符串或符号)。然而,由于它们被很多人用作查找表,因此大多数引擎会选择像数据结构这样的哈希表来在内部实现对象(在某些情况下)。所以是的,您可以将对象用作哈希表(但不能保证引擎实际上会在引擎盖下使用哈希表)。

your keys are strings or numbers ...

你的键是字符串或数字......

No. Numbers will be casted to string when used as object keys, just as any other value. Therefore you can use Objects as a hashtable for numbers, and for strings, but not for both at the same time:

不会。当用作对象键时,数字将被转换为字符串,就像任何其他值一样。因此,您可以将对象用作数字和字符串的哈希表,但不能同时用于两者:

  { "1": true }[1] // true

If you need a Hashtable for arbitrary / mixed values, a Mapor a Setwill be the better choice, especially because they guarantee O(1) lookup time.

如果您需要任意/混合值的哈希表,aMap或 aSet将是更好的选择,尤其是因为它们保证 O(1) 查找时间。

回答by John Green

Yes, keys can be numbers. In fact, the specification utilizes the same generic mapping functions for both Objects and Arrays.

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