18

Given an object literal, or jQuery(html, attributes) object, does any specification state that reserved words, or future reserved words MUST be quoted?

Or, can, for example, class be set as a property name of an object without using quotes to surround the property name, without the practice being contrary to a specification concerning identifiers, property names, or use of reserved words?

Seeking a conclusive answer as to this question to avoid confusion.

let objLit = {
  class: 123,
  var: "abc",
  let: 456,
  const: "def",
  import: 789
}

console.dir(objLit);

jQuery("<div>012</div>", {
  class: "ghi"
})
.appendTo("body");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>

Related:

Specification

Identifier Names are tokens that are interpreted according to the grammar given in the “Identifiers” section of chapter 5 of the Unicode standard, with some small modifications.
An Identifier is an IdentifierName that is not a ReservedWord

Andrew Li
  • 55,805
  • 14
  • 125
  • 143
guest271314
  • 1
  • 15
  • 104
  • 177
  • @AndrewLi - that answer says *"NOT be used as identifier names"* and the [spec](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer) says PropertyNames are *"IdentifierNames"*, so it's quite confusing. Identifiers are not very well described in the ES5 spec, but it does say things like *"property names become visible identifiers bindings"* and *"all the properties of Object.prototype are visible as identifiers within that scope"* so it's hard to tell what's what ? – adeneo Oct 24 '16 at 01:18
  • @RobG - If a property name is an "identifier", it clearly can't be a reserved keyword, yet this [answer](http://stackoverflow.com/questions/4348478/what-is-the-difference-between-object-keys-with-quotes-and-without-quotes#answer-9568622) says otherwise, and claims a PropertyName is not an identifier – adeneo Oct 24 '16 at 01:20
  • @adeneo If you feel like the duplicate or others do not answer it clearly, you're free to reopen as you wish and answer accordingly. I'm also curious about this topic, so I'm open to any other clarifications – Andrew Li Oct 24 '16 at 01:25
  • @AndrewLi - I'm not an avid reader of the spec, so I don't know, but the way I read the part of the spec above, is that they're saying that `IdentifierName` is a name according to the Unicode standard, but when used for an identifier it also can't be a reserved keyword, which makes sense. However, it seems most answers believe "identifier" to be a variable/function name only, and not apply for PropertyName. Just skimming the ES5 spec I couldn't see anything that describes an "identifier" properly, nor anything about PropertyNames not being one? – adeneo Oct 24 '16 at 01:31
  • @adeneo Another interesting case is, if for example `class` can be used as a property name of an object, that does not mean that the property can be accessed similar to properties which are not reserved words. `let objLit = {class:123, abc:456}; var {class} = objLit;//Uncaught SyntaxError: Unexpected token } var {abc} = objLit; abc // 456`. Though it is possible to access the property by assigning a variable which is not reserved word `var {class:a} = objLit; a//123` – guest271314 Oct 24 '16 at 01:37
  • @adeneo It seems that `PropertyName` should be an `IdentifierName`, as seen [here](https://people.mozilla.org/~jorendorff/es5.html#sec-11.1.5), suggesting that property names cannot be reserved keywords, mentioned [here](https://people.mozilla.org/~jorendorff/es5.html#sec-7.6). – Andrew Li Oct 24 '16 at 01:40
  • @AndrewLi _"suggesting that property names cannot be reserved keywords..."_ Then, what is the correct Answer to the present Question? – guest271314 Oct 24 '16 at 01:44
  • @guest271314 That I'm not sure of. Since it's clear that the duplicate isn't clear I've nominated for reopening - I'll search in the spec a bit more and see if anyone can answer. – Andrew Li Oct 24 '16 at 01:46
  • @AndrewLi - but it says that "An Identifier is an IdentifierName that is not a ReservedWord" implying that an `IdentifierName` can be a reserved word, unless it's used for an identifier? But on the other hand, what else would it be used for, you'd think that `IdentifierName` is used for "identifiers", and for a variable is quite clear, it's defined as `Identifier = Initialiser`, so it's clearly an identifier, so why wouldn't a propertyName be as well? Of course, the fact that it doesn't work in destructuring, makes it just more confusing? – adeneo Oct 24 '16 at 01:46
  • @adeneo It mentions that an `Identifier` *is* an `IdentifierName` that isn't a `ReservedWord` - which means **`PropertyName` is implicitly allowed to be a `ReservedWord`.** As for destructuring, I'm not entirely sure. The [ES6 spec](http://www.ecma-international.org/ecma-262/6.0/#sec-destructuring-assignment) doesn't really offer much about this. – Andrew Li Oct 24 '16 at 01:54
  • When you say "any specification", do you mean "any rule in the ECMAScript specification", or are you trying to include specs other than the ECMAScript spec, sort of like what the POSIX spec or MISRA C might be for C? – user2357112 Oct 24 '16 at 01:55
  • 1
    @user2357112 MDN is not a specification, ECMAScript® Language Specification includes the name "Specification" in the title. Seeking clarification concerning the Question from credible sources which compose documentation as to how the language is intended to be used. Or, from an author, or even user of the language who is familiar with the language at the core level. – guest271314 Oct 24 '16 at 01:58
  • @AndrewLi `class` would become an `IndentifierName` if allowed to be set as variable, or `Identifier` `class` outside of the object at `var {class} = objLit;`? Can we conclude that if a syntax error is not thrown, the syntax is probably within the bounds of the intended use? With the caveat that outside of `{}` the property name cannot be directly set as an identifier like properties which as not reserved words. – guest271314 Oct 24 '16 at 02:06
  • @guest271314 The [ES5 Spec](https://people.mozilla.org/~jorendorff/es5.html#sec-12.2) suggests that a variable declaration must have an `Identifier`, not `IdentifierName` likely explaining syntax error (although I'm not sure. Not a usual spec reader). – Andrew Li Oct 24 '16 at 02:13
  • I can somewhat positively conclude the reason why `var {class: a} = ...` works because we have a (somewhat) object literal, where `PropertyName` which is `class` here, is allowed to be a `ReservedWord`, but `var {class}` doesn't work because here, `class` is an `Identifier`. I may be wrong and my terminology may be off. – Andrew Li Oct 24 '16 at 02:14
  • @AndrewLi `class` syntax outside of `{}` is expecting `class SomeName {constructor(){}//stuff}`: `class` space character identifier that is not a reserved word then `{}`. That is `class` alone also logs an error `Uncaught SyntaxError: Unexpected end of input`. – guest271314 Oct 24 '16 at 02:19
  • Oh yes, you're correct. I'm just not entirely sure about destructuring - it's possible that, as mentioned before `var {class: a} = ...` is allowed because `{class: a}` is considered to be a literal where `class` is a `PropertyName` thus an `IdentifierName`, which is allowed to be a `ReservedWord` and does not throw a syntax error. I'm no expert on this, so if anyone else would like to weigh in, I'm open. – Andrew Li Oct 24 '16 at 02:21
  • If `var {class} = objLit` was allowed, `class` would essentially overwrite `class`; and `class` could be written without `Uncaught SyntaxError: Unexpected end of input`. There would be no way for `javascript` to determine which is which. `var {class:a} = objLit` assigns the value of `class` property within `objLit` to `a` identifier. – guest271314 Oct 24 '16 at 02:23
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/126481/discussion-between-andrew-li-and-guest271314). – Andrew Li Oct 24 '16 at 02:25
  • @adeneo From your vantage, does AndrewLi's Answer definitively resolve Question? – guest271314 Oct 24 '16 at 04:09
  • 2
    @guest271314 - assuming he's correct, it does. The real question for me isn't if it works or not, it seems all interpreters today are smart enough to understand that a reserved keyword used in curlybraces doesn't conflict, but outside curlybraces it's always a risk. The spec says propertyName of an object can be a string, number or identifierName, but passing in an array, object, or anything else as a key, is just fine as well, even if it's not in the spec. Also, ES6 classes seem to have names that are "propertyName", and should accept anything as well, but you really can't do `class class`. – adeneo Oct 24 '16 at 11:27
  • 2
    @adeneo Note, it is in (6.0) [the spec](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer): `PropertyName` may be a `ComputedPropertyName`, and a `ComputedPropertyName` can be an `AssignmentExpression` thus allowing many things as keys. Also, on the [spec](http://www.ecma-international.org/ecma-262/6.0/#sec-class-definitions), it mentions the syntax is `class BindingIdentifier`, where [`BindingIdentifier` is an `Identifier`](http://www.ecma-international.org/ecma-262/6.0/#sec-identifiers) thus not a `ReservedWord`. – Andrew Li Oct 24 '16 at 13:17

3 Answers3

28

ECMAScript 5+

No, quotes were not needed since ECMAScript 5. Here's why:

As mentioned in your post, from the ECMAScript® 5.1 Language Specification:

7.6 Identifier Names and Identifiers

Identifier Names are tokens that are interpreted according to the grammar given in the “Identifiers” section of chapter 5 of the Unicode standard, with some small modifications. An Identifier is an IdentifierName that is not a ReservedWord (see 7.6.1).

[...]

Syntax

Identifier ::
  IdentifierName but not ReservedWord

By specification, a ReservedWord is:

7.6.1 Reserved Words

A reserved word is an IdentifierName that cannot be used as an Identifier.

Syntax

ReservedWord :: 
  Keyword
  FutureReservedWord
  NullLiteral
  BooleanLiteral

This includes keywords, future keywords, null, and boolean literals. The full list is as follows:

7.6.1.1 Keywords

break    do       instanceof typeof
case     else     new        var
catch    finally  return     void
continue for      switch     while
debugger function this       with
default  if       throw 
delete   in       try   

7.6.1.2 Future Reserved Words

class enum   extends super
const export import

7.8.1 Null Literals

null

7.8.2 Boolean Literals

true
false

The above (Section 7.6) implies that IdentifierNames can be ReservedWords, and from the specification for object initializers:

11.1.5 Object Initialiser

[...]

Syntax

ObjectLiteral :
  { }
  { PropertyNameAndValueList }
  { PropertyNameAndValueList , }

Where PropertyName is, by specification:

PropertyName :
  IdentifierName
  StringLiteral
  NumericLiteral

As you can see, a PropertyName may be an IdentifierName, thus allowing ReservedWords to be PropertyNames. That conclusively tells us that, by specification, it is allowed to have ReservedWords such as class and var as PropertyNames unquoted just like string literals or numeric literals.


ECMAScript <5

To go more in depth as to why this wasn't allowed in previous versions before ES5, you have to look at how PropertyName was defined. Per the ECMAScript® 3 Language Specification:

PropertyName :
  Identifier
  StringLiteral
  NumericLiteral

As you can see, PropertyName was an Identifer - not an IdentifierName, thus leading to the inability for ReservedWords as PropertyNames.

Andrew Li
  • 55,805
  • 14
  • 125
  • 143
  • 2
    As a side note, the reason why the JSON format requires all property names to be quoted is that the standard was laid out in ES3 times and Douglas Crockford did not want to include reserved words into the JSON specifications ([reference](https://youtu.be/-C-JoyNuQJs?t=300)). – Oliver Sieweke Nov 09 '20 at 13:54
3

Given an object literal, or jQuery (html, attributes) object, does any specification state that reserved words, or future reserved words MUST be quoted?

No (starting with ES5).

The definition of property in the spec is that it is any identifier name. class is a perfectly good identifier name.

As others have pointed out in the comments, according to the spec, the property name in an object literal may be an (unquoted) IdentifierName (in addition to being a string etc.). IdentifierName is, for all practical purposes, any sequence of Unicode "letters", as given in section 7.6.

Note that the syntax error generated by

const {class} = obj;

is not an exception. That's not an object literal, which is what the question is about; it's an assignment (or the destructuring kind), which attempts to assign a variable class. Of course you can't, never have been able to, and never will be able to have variables which are named with reserved words.

See also this blog post, which although not authoritative is a reliable, high-quality source of information about all things ES5/6/7.

Note that in ES3, the definition of PropertyName was Identifier, not IdentifierName as in ES5. That prevented using properties such as class, since class is not an identifier. It was this change that permitted the use of unquoted reserved words as properties in object literals (as well as in dot notation).

With regard to "jQuery objects", a "jQuery object" is just a regular old JS object. Do you mean the DOM elements held by jQuery objects? They are a kind of hybrid of native objects and JS objects. As JS objects, they can have properties. However, they cannot be written in object literal form, so the question does not really apply to them. (As native (DOM) objects, they can have attributes, the latter case not being covered by the JS spec.)

  • Did not state that `const {class} = obj;` is an object literal. Where did you read that? No, the jQuery example is how this Question came about for this user. That is where `{class:"someClassName"}` has been most seen by this user. See http://stackoverflow.com/a/40208959/ , http://stackoverflow.com/a/36638058/ . You really came barreling in here. Perhaps you will resolve the Question, after reading the Question again, and the comments attached hereto. – guest271314 Oct 24 '16 at 02:57
  • 1
    The OP doesn't think that `const {class} = obj;` was an object literal - you might've confused him/her with me. I confused it with an object literal in comments on accident. – Andrew Li Oct 24 '16 at 02:57
  • @torazaburo Do not "downvote" here, though some of the portions of your current Answer reveal a lack of having actually read the Question, and comments? And yet, you have still not edited your Answer. What have you added to the discussion? _"`const {class} = obj;`That's not an object literal,"_ Did OP state that is an object literal at actual Question? – guest271314 Oct 24 '16 at 03:05
  • @guest271314 I never said the OP said that `const {class} = obj;` was an object literal. That part of my answer is merely clarifying. How would you like me to edit my answer? –  Oct 24 '16 at 03:11
  • The portion concerning destructuring assignment was a caveat discussed at comments, not necessary a part of the actual Question. jQuery was used as an example because that is where this user has most, if not exclusively seen `{class:"someClassName"}` used. Explain the caveats of using keywords or reserved words. – guest271314 Oct 24 '16 at 03:14
  • @guest271314 Well, I am not aware of any caveats. Reserved words may be used as unquoted property names in any and all situations, period. –  Oct 24 '16 at 03:15
0

This answer cannot compete with those already given but I'd love to chime in nonetheless.

In my code I prefer to ALWAYS quote keys, for example:

var o;

o = {
  "label": "Hello",
  "index": 3
};

This way, the problem of strange names or reserved keywords doesn't even arise. Furthermore, all object literals are written in a style that is very near to valid JSON, as an added bonus copy+paste into a separate JSON file (and vice-versa) can be done very quickly.

Today, I consider this a must-have style for clean code.

pid
  • 11,472
  • 6
  • 34
  • 63