82

I'm trying to work out what is considered valid for the property name of a javascript object. For example

var b = {}
b['-^colour'] = "blue";     // Works fine in Firefox, Chrome, Safari
b['colour'] = "green";      // Ditto
alert(b['-^colour']);       // Ditto
alert(b.colour);            // Ditto
for(prop in b) alert(prop); // Ditto
//alert(b.-^colour);     // Fails (expected)

This post details valid javascript variable names, and '-^colour' is clearly not valid (as a variable name). Does the same apply to object property names? Looking at the above I'm trying to work out if

  1. b['-^colour'] is invalid, but works in all browsers by quirk, and I shouldn't trust it to work going forward

  2. b['-^colour'] is completely valid, but it's just of a form that can only be accessed in this manner - (it's supported so Objects can be used as maps perhaps?)

  3. Something else

As an aside, a global variable in javascript might be declared at the top level as

var abc = 0;

but could also be created (as I understand it) with

window['abc'] = 0;

the following works in all the above browsers

window['@£$%'] = "bling!";
alert(window['@£$%']);

Is this valid? It seems to contradict the variable naming rules - or am I not declaring a variable there? What's the difference between a variable and an object property name?

Community
  • 1
  • 1
hawkett
  • 3,053
  • 5
  • 29
  • 39

3 Answers3

73

Yes, objects can be used as maps, and any string can be a property name. As you've discovered, some properties can only be accessed using the bracket syntax.

window['abc']

is accessing a property. It is not a variable, even though it refers to the same value (at the global level) as:

abc
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • 61
    "An object property name can be any valid JavaScript string, or anything that can be converted to a string, including the empty string. However, any property name that is not a valid JavaScript identifier (for example, a property name that has a space or a hyphen, or that starts with a number) can only be accessed using the square bracket notation." ([MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties)) – molnarm Feb 10 '14 at 13:51
  • 14
    ***Márton raises a very important point.*** While at first it may appear as though any JS object can take anything as a valid object key, it isn't quite the case -- Márton correctly points out that such property keys are actually converted to strings. Consider `var x=new function X(){};`, `var y=new function Y(){};`, and `obj={x:true};` -- `obj[y]` will output `true`, because both `x` and `y`, when used as an object key, are both converted to the same string `"[object Object]"` – ChaseMoskal Apr 01 '14 at 20:44
  • 5
    To be clear, given my previous comment's example, `obj[x] === obj[y] === obj["[object Object]"]` – ChaseMoskal Apr 01 '14 at 20:47
  • 1
    I'll point out that the reason for restrictions on identifier names (even though JS could presumably handle any string internally as a variable or property identifier) is primarily to avoid syntactical ambiguity. Consider a property name with a dash: `x=obj.my-prop`. It would be unclear (both to the reader and the parser) if that's a property named "my-prop" or if the intent was to subtract a variable "prop" from "obj.my". `x=obj["my-prop"]` makes it clear the name is a string. – wojtow Oct 16 '20 at 23:29
15

Object property naming rules and variable naming rules are separate. The standard only "reserves" a handful of property names (such as prototype and constructor, IIRC), but other than those, any string goes.

Except when the execution environment (i.e. the browser) decides to add more magic properties, of course. (I hear setting __proto__ breaks some things in quite weird ways)

Matti Virkkunen
  • 63,558
  • 9
  • 127
  • 159
  • Thanks Matti - tough to work out who to give the answer, both answered, but with different (useful) information - went with first answer. Cheers. – hawkett May 30 '10 at 21:54
  • 1
    when you set `__proto__` to null, what does that break except for the prototype chain (so it's a faster property lookup), if you need it as a simple hash table for value pairs? – Dimitar Christoff Jun 01 '11 at 11:58
9
  1. Every time you create a global variable you create in fact a new member of a global object (which is window in browser environment, global in Node.js, etc.). This is why window.x is exactly the same like (global) var x, this.x or just x.

  2. Understanding JavaScript object like a map is quite right, because: a) you can add a new element dynamically - at any moment; b) the element can have any name - also including special characters, c) you can try to access a non-existing element of an object/map and it is not an error, d) you can remove an element from an object.

  3. If you like to access object members with standard dot notation (eg. a.x) you are not allowed to use any special characters different than _ or $; also the name cannot start from a number. For all other cases you are forced to use square brackets and quotation marks to access object elements.

ytropek
  • 759
  • 6
  • 7