Updated Question
What, exactly, qualifies as a valid property name in Javascript? How do various methods of property assignment differ? And how does the property name affect property access?
Note
The answers to my original question (seen below) helped to clear some things up, but also opened a new can of worms. Now that I've had a chance to become a bit more familiar with JavaScript, I believe I've been able to figure a lot of it out.
Since I had a hard time finding this information consolidated into one explanation, I thought it might be helpful to expand my original question, and attempt to answer it.
Original Question
Originally, there was some confusion with the MDN JavaScript guide (object literals). Specifically, I wondered why they claimed that if a property name was not a valid JavaScript identifier, then it would have to be enclosed in quotes. Yet, they offered example code that showed that the number 7 could be used — without quotes — as a property name.
As it turns out, the guide simply left off one important part, and Pointy updated it (changes in bold):
If the property name would not be a valid JavaScript identifier or number, it must be enclosed in quotes.
I also wondered why property names were allowed to deviate away from the "may not start with a digit" rule, that applies to identifiers. That question actually reveals the complete misunderstanding that I had of property names, and is what lead me to do some more research.
Answer for 1st question:
Yes, the statement given in the MDN guide is not 100% accurate, but in your daily work it'd be better to follow it as rule. You really don't need to create properties names which are numbers.
Answer for 2nd question:
A property name may not start with a digit but a property name that is a number without any other characters in its name is fine.
This exception exists because the properties with number for name as the same as indexes
.
Let's try this:
var obj = {7: "abc"};
obj[7]; // works fine
obj.7; // gives an error (SyntaxError)
Now try to call Array.push
on the object and observe what happens:
Array.prototype.push.call(obj, "xyz");
console.log(obj);
console.log(obj[0]);
// Prints
Object {0: "xyz", 7: "abc", length: 1}
"xyz"
You can see that few new properties (one with name 0
and another with name length
) have been added to the object. Moreover, you can use the object as an array:
var obj = { "0": "abc", "1": "xyz", length: 2 };
Array.prototype.pop.call(obj); // Returns: "xyz"
Array.prototype.pop.call(obj); // Returns: "abc"
You can use array's methods on objects and this is called Duck Typing
.
Arrays are nothing more than objects with some predefined methods.
From MDN:
Array elements are object properties in the same way that length is a property, but trying to access an element of an array with dot notation throws a syntax error, because the property name is not valid. There is nothing special about JavaScript arrays and the properties that cause this. JavaScript properties that begin with a digit cannot be referenced with dot notation and must be accessed using bracket notation.
Now you can understand why a number for property name is valid. These are called just indexes and they are used in JavaScript arrays. And since JavaScript needs to be consistent with other languages, numbers are valid for indexes/properties names.
Hope this makes it clear.
Here are some interesting articles:
- JavaScript identifiers (in ECMAScript 5)
- JavaScript identifiers (in ECMAScript 6)
Short Answer
Object property names can be any valid identifier, numeric literal, or string literal (including the empty string).
With that said, there are some potentially confusing intricacies to keep in mind about JavaScript property names (the summary is given below, and explored more on my own).
Negative Numbers
What might look like a negative number is actually an expression — something property names do not support.
var obj = {
-12: 'nope' // I am an invalid property name, because I am an expression.
};
Fortunately, bracket notation handles expressions for us.
obj[-6] = 'yup'; // Successful property assignment. We're good here.
Parsing & Typecasting
All property names are typecasted into strings before being stored.
var obj = {
lego: 'Everything is cool when you\'re part of a string.'
};
for (var key in obj) console.log(key); // "lego"
But even before that, they are parsed according to the syntax used, and transformed into a decimal literal.
var objValid = {
'022': 'alligator', // valid string literal
6: 'cow', // interpreted as decimal, evaluates to 6
.345: 'bear', // interpreted as floating-point; evaluates to 0.345
1.000: 'fox', // interpreted as floating-point, evaluates to 1
8.9890: 'owl', // interpreted as floating-point, evaluates to 8.989
000888: 'fish', // interpreted as decimal, evaluates to 888
0777: 'monkey', // interpreted as octal, evaluates to 511
0x00111: 'elephant', // interpreted as hexadecimal, evaluates to 273
0b0011: 'donkey', // interpreted as binary, evaluates to 3
};
console.log(objValid['022']); // "alligator"; as expected
console.log(objValid[022]); // undefined; 022 is an octal literal that evaluates to 18 before our lookup ever occurs
console.log(objValid[6]); // "cow"; as expected
console.log(objValid['6']); // "cow"; as expected
console.log(objValid[0777]); // "monkey"; we're accessing the property name as it was assigned (before it was parsed and typecasted)
console.log(objValid['0777']); // undefined; after parsing and typecasting, our property name seems to have disappeared
console.log(objValid['511']); // "monkey"; there it is, we found it using the evaluation of our original assignment
console.log(objValid[0x00111]); // "elephant"; we're accessing the property name as it was assigned (before it was parsed and typecasted)
console.log(objValid['0x00111']); // undefined; after parsing and typecasting, our property name seems to have disappeared
console.log(objValid['273']); // "elephant"; there it is, we found it using the evaluation of our original assignment
console.log(objValid[0b0011]); // "donkey"; we're accessing the property name as it was assigned (before it was parsed and typecasted)
console.log(objValid['0b0011']); // undefined; after parsing and typecasting, our property name seems to have disappeared
console.log(objValid['3']); // "donkey"; there it is, we found it using the evaluation of our original assignment
Conclusion
Unless you're working with valid (non-negative integer) array indexes — explicitly assign all numerical property names as strings.