How exactly is the JavaScript expression [1 [{}]] parsed?

Can you explain how a JavaScript expression is:

[1 [{}]] 

parses / evaluates? Firefox, Chrome, Konqueror, and Rhino create an array with one undefined element. However, I do not understand why.

In Firefox:

 [1 [{}]].toSource() 

produces

 [(void 0)] 

Replacing 1 with other JavaScript values โ€‹โ€‹seems to give the same result.

Update: I think I understand now. codeka, Adrian and CMS clarified the situation. Regarding the standard, I tried to go through ECMAScript 5.

  • 1 [{}] is an Access Accessor, therefore it is described in ยง11.2.1.
  • baseReference is the result of a score of 1 , so another 1 .
  • baseValue = GetValue(baseReference) == 1 .
  • In GetValue (ยง8.7.1), Type(1) not Reference (binding resolved names), so return 1.
  • propertyNameReference is the result of evaluating {} , therefore an empty object.
  • propertyNameValue = GetValue(propertyNameReference) == {}
  • In CheckObjectCoercible(baseValue) (ยง9.10) we return (the number is object-coherent).
  • propertyNameString = ToString(propertyNameValue)
  • In ToString (ยง9.8) return ToString(ToPrimitive({}, hint String))
  • In ToPrimitive (ยง9.1) return the result of the [[DefaultValue]] object by passing PreferredType (string).
  • In [[DefaultValue]] (ยง8.12.8), let toString be the result of [[Get]] with the ToString argument.
  • This is defined in ยง15.2.4.2 to return "[object " + [[Class]] + "]" , where [[Class]] is the "Object" for the default prototype of the object.
  • Since there is a callable ToString , we call it the argument this {} .
  • Returns a value of type Reference , whose base value is BaseValue (1) and whose link name is propertyNameString ( "[object Object]" ).

Then go to the Array initializer (ยง11.1.4) and build an array of elements with the result.

+6
javascript parsing literals
source share
3 answers

If we break it up a bit, you will see:

 var foo = 1; var bar = {}; var baz = foo[bar]; [baz]; 

I believe this is valid JavaScript, but I am not an expert ...

+7
source share

Reading the OP and Nick's comments , I think I can expand Adrian's answer a bit to make it clearer.

Perfectly valid JavaScript.

JavaScript treats object object names as strings, objects cannot contain other types or other objects as keys, they are just strings.

The bracket designation of the accessor property ( MemberExpression [ Expression ] ) implicitly converts the expression between the brackets to a string, therefore:

 var obj = {}; obj[{}] = "foo"; alert(obj["[object Object]"]); // foo 

In the above example, you can see that I am assigning a value to the {} property, and {}.toString() (or {}+'' ) creates the string "[object Object] (via Object.prototype.toString ).

Expression 1 [{}] implicitly converts the primitive 1 Number to an object (this is done by the property accessory), and it searches for a property with the name "[object Object]" , the search for properties is performed on Number.prototype and Object.prototype , for example:

 1['toString'] === Number.prototype.toString; // true 

Finally, the expression 1 [{}] itself enclosed in brackets ( [1 [{}]] ), it is actually an Array literal.

In conclusion, here is how the analyzer evaluates the expression:

  [1 [{}]]; // ^ The accessor expression is evaluated and converted to string [1 ["[object Object]"]]; // ^ A property lookup is made on an Number object // trying to access a property named "[object Object]" [undefined]; // ^ the property is obviously not found [undefined]; //^ ^ // An array literal is created with an element `0` which its value is `undefined` 
+15
source share

This is because you are trying to get the {} property of object 1 , and then put it in an array. 1 does not have the {} property, therefore 1[{}] is undefined .

If you replace 1 with an array, you will see how it works. With 1 as [5] and {} as 0 it is [[5][0]] .

Also, keep in mind that obj['property'] same as obj.property .

+8
source share

All Articles