Mathias Bynens

Unquoted property names / object keys in JavaScript

· tagged with JavaScript

Fun fact: var foo = { H̹̙̦̮͉̩̗̗ͧ̇̏̊̾Eͨ͆͒̆ͮ̃͏̷̮̣̫̤̣Cͯ̂͐͏̨̛͔̦̟͈̻O̜͎͍͙͚̬̝̣̽ͮ͐͗̀ͤ̍̀͢M̴̡̲̭͍͇̼̟̯̦̉̒͠Ḛ̛̙̞̪̗ͥͤͩ̾͑̔͐ͅṮ̴̷̷̗̼͍̿̿̓̽͐H̙̙̔̄͜: 42 }; is valid JavaScript. It may not be immediately obvious, but the real surprise here is that the Cthulhu-esque property name is not surrounded by quotes. Intrigued by this, and having written about the similar topic of JavaScript identifiers before, I decided to look into valid property names in JavaScript. When do they need to be quoted? When can the quotes be omitted? And in which cases can dot notation be used instead of bracket notation to get or set a property based on its name?

Valid property names

Looking at the ECMAScript 5 spec grammar, we can see that a property name can be either an identifier name (i.e. identifiers + reserved words), a string literal, or a numeric literal.

Identifier names are a superset of identifiers; any valid identifier and any reserved word is a valid identifier name.

A string literal is any valid string, encapsulated in either single (') or double (") quotes. 'foo', "bar", 'qu\'ux', "" (the empty string), and 'Ich \u2665 B\xFCcher' are all valid string literals.

A numeric literal can be either a decimal literal (e.g. 0, 123, 123., .123, 1.23, 1e23, 1E-23, 1e+23, 12, but not 01, +123 or -123) or a hex integer literal (0[xX][0-9a-fA-F]+ in regex, e.g. 0xFFFF, 0X123, 0xaBcD).

Technically, octal literals (0[0-7]+ in regex, e.g. 010, 012, 01) are valid numeric literals too, but as they’re not allowed in strict mode it’s probably best to avoid them altogether.

The spec defines property names as strings:

The Property Identifier type is used to associate a property name with a Property Descriptor. Values of the Property Identifier type are pairs of the form (name, descriptor), where name is a String and descriptor is a Property Descriptor value.

This can make the use of numeric literals as property names a bit confusing. For example, if you were to use the number .12e3 as an (unquoted) property name, it would be coerced into a string first, and the actual object key would become '120'.

var object = {
.12e3: 'wut'
};
object[.12e3]; // 'wut'
object['.12e3']; // undefined
object['120']; // 'wut'

// Let’s try another numeric literal:
object = {
12e34: 'heh'
};
object[12e34]; // 'heh'
object['12e34']; // undefined
object[1.2e35]; // 'heh'
object['1.2e35']; // undefined
object[1.2e+35]; // 'heh'
object['1.2e+35']; // 'heh'

While you can easily check the string value of any number — String(number) or (number).toString() — it’s definitely simpler to just stick to string literals or identifier names for property names.

Note: ECMAScript 3 didn’t allow the use of unquoted reserved words as property names. Here’s the full list of ES3 reserved words: abstract, boolean, break, byte, case, catch, char, class, const, continue, debugger, default, delete, do, double, else, enum, export, extends, false, final, finally, float, for, function, goto, if, implements, import, in, instanceof, int, interface, long, native, new, null, package, private, protected, public, return, short, static, super, switch, synchronized, this, throw, throws, transient, true, try, typeof, var, void, volatile, while, and with. Avoid using these as unquoted property names if backwards compatibility is a concern.

When can the quotes be omitted?

Unless an object key is a numeric literal or a valid identifier name, you need to quote it to avoid a syntax error from being thrown. In other words, quotes can only be omitted if the property name is a numeric literal or a valid identifier name. Of course, if the property name is a string literal, it’s already quoted by definition.

var object = {
// `abc` is a valid identifier; no quotes are needed
abc: 1,
// `123` is a numeric literal; no quotes are needed
123: 2,
// `012` is an octal literal with value `10` and thus isn’t allowed in strict mode; but if you insist on using it, quotes aren’t needed
012: 3,
// `π` is a valid identifier; no quotes are needed
π: Math.PI,
// `var` is a valid identifier name (although it’s a reserved word); no quotes are needed
var: 4,
// `foo bar` is not a valid identifier name; quotes are required
'foo bar': 5,
// `foo-bar` is not a valid identifier name; quotes are required
'foo-bar': 6,
// the empty string is not a valid identifier name; quotes are required
'': 7
};

JSON only allows string literals that are quoted in double quotes (") as property names.

When can dot notation be used?

To get or set a value from an object based on a property name, you can always use bracket notation. Let’s say we want to get the value for the property name abc from the object in the previous example this way:

object['abc']; // 1

Bracket notation can safely be used for all property names.

As you may know, there is an alternative that can be used in some cases: dot notation.

object.abc; // 1

Dot notation can only be used when the property name is a valid identifier name. It cannot be used for property names that are numeric literals, or for strings that aren’t valid identifier names.

Unquoted JavaScript property name validator

I made a tool that will tell you if any given property name can be used without quotes and/or with dot notation. Try it at mothereff.in/js-properties.

Unquoted JavaScript property name validator

Comments

bird wrote on :

Could you explain why the number .12e3 implicitly converts to the string "120"? Thank you very much.

hite wrote on :

I still don’t understand why object['1.2e+35'] is 'heh' while object['1.2e35'] is undefined. It confuses me so much.

I tried the following:

>>> String('1.2e+35')
"1.2e+35"
>>> String('1.2e35')
"1.2e35"
>>> Number('1.2e+35').toString()
"1.2e+35"
>>> Number('1.2e35').toString()
"1.2e+35"
>>> parseFloat('1.2e36')
1.2e+36
>>> parseFloat('1.2e+36')
1.2e+36

Both of them appear to be exactly the same, but object['1.2e35'] != object['1.2e+35'].

wrote on :

hite: object[1.2e35] == object[1.2e+35] is always true, since in both cases, the property with the name '1.2e+35' is accessed.

The result of object['1.2e35'] == object['1.2e+35'] cannot be guaranteed since '1.2e35' and '1.2e+35' are different strings, and therefore different property names.

Leave a comment

Comment on “Unquoted property names / object keys in JavaScript”

Some Markdown is allowed; HTML isn’t. Keyboard shortcuts are available.

It’s possible to add emphasis to text:

_Emphasize_ some terms. Perhaps you’d rather use **strong emphasis** instead?

Select some text and press + I on Mac or Ctrl + I on Windows to make it italic. For bold text, use + B or Ctrl + B.

To create links:

Here’s an inline link to [Google](http://www.google.com/).

If the link itself is not descriptive enough to tell users where they’re going, you might want to create a link with a title attribute, which will show up on hover:

Here’s a [poorly-named link](http://www.google.com/ "Google").

Use backticks (`) to create an inline <code> span:

In HTML, the `p` element represents a paragraph.

Select some inline text and press + K on Mac or Ctrl + K on Windows to make it a <code> span.

Indent four spaces to create an escaped <pre><code> block:

    printf("goodbye world!"); /* his suicide note
was in C */

Alternatively, you could use triple backtick syntax:

```
printf("goodbye world!"); /* his suicide note
was in C */
```

Select a block of text (more than one line) and press + K on Mac or Ctrl + K on Windows to make it a preformatted <code> block.

Quoting text can be done as follows:

> Lorem iPad dolor sit amet, consectetur Apple adipisicing elit,
> sed do eiusmod incididunt ut labore et dolore magna aliqua Shenzhen.
> Ut enim ad minim veniam, quis nostrud no multi-tasking ullamco laboris
> nisi ut aliquip iPad ex ea commodo consequat.

Select a block of text and press + E on Mac or Ctrl + E on Windows to make it a <blockquote>.