Friday, May 10, 2024
 Popular · Latest · Hot · Upcoming
150
rated 0 times [  153] [ 3]  / answers: 1 / hits: 6910  / 9 Years ago, wed, march 25, 2015, 12:00:00

Why is this line valid in javascript ?



var a = 0[0];


After that, a is undefined.


More From » javascript

 Answers
49

When you do 0[0], the JS interpreter will turn the first 0 into a Number object and then try to access the [0] property of that object which is undefined.



There is no syntax error because the property access syntax 0[0] is allowed by the language grammar in this context. This structure (using terms in the Javascript grammar) is NumericLiteral[NumericLiteral].



The relevant part of the language grammar from section A.3 of the ES5 ECMAScript spec is this:



Literal ::
NullLiteral
BooleanLiteral
NumericLiteral
StringLiteral
RegularExpressionLiteral

PrimaryExpression :
this
Identifier
Literal
ArrayLiteral
ObjectLiteral
( Expression )

MemberExpression :
PrimaryExpression
FunctionExpression
MemberExpression [ Expression ]
MemberExpression . IdentifierName
new MemberExpression Arguments


So, one can follow the grammer through this progression:



MemberExpression [ Expression ]
PrimaryExpression [ Expression ]
Literal [ Expression ]
NumericLiteral [ Expression ]


And, similarly Expression can also eventually be NumericLiteral so after following the grammar, we see that this is allowed:



NumericLiteral [ NumericLiteral ]


Which means that 0[0] is an allowed part of the grammar and thus no SyntaxError.






Then, at run-time you are allowed to read a property that does not exist (it will just be read as undefined) as long as the source you are reading from either is an object or has an implicit conversion to an object. And, a numeric literal does indeed have an implicit conversion to an object (a Number object).



This is one of those often unknown features of Javascript. The types Number, Boolean and String in Javascript are usually stored internally as primitives (not full-blown objects). These are a compact, immutable storage representation (probably done this way for implementation efficiency). But, Javascript wants you to be able to treat these primitives like objects with properties and methods. So, if you try to access a property or method that is not directly supported on the primitive, then Javascript will temporarily coerce the primitive into an appropriate type of object with the value set to the value of the primitive.



When you use an object-like syntax on a primitive such as 0[0], the interpreter recognizes this as a property access on a primitive. Its response to this is to take the first 0 numeric primitive and coerce it into a full-blown Number object which it can then access the [0] property on. In this specific case, the [0] property on a Number object is undefined which is why that's the value you get from 0[0].



Here is an article on the auto-conversion of a primitive to an object for purposes of dealing with properties:



The Secret Life of Javascript Primitives






Here are the relevant portions of the ECMAScript 5.1 specification:



9.10 CheckObjectCoercible



Throws TypeError if value is undefined or null, otherwise returns true.



enter



11.2.1 Property Accessors





  1. Let baseReference be the result of evaluating MemberExpression.

  2. Let baseValue be GetValue(baseReference).

  3. Let propertyNameReference be the result of evaluating Expression.

  4. Let propertyNameValue be GetValue(propertyNameReference).

  5. Call CheckObjectCoercible(baseValue).

  6. Let propertyNameString be ToString(propertyNameValue).

  7. If the syntactic production that is being evaluated is contained in strict
    mode code, let strict be true, else let strict be false.

  8. Return a value of type Reference whose base value is baseValue and whose
    referenced name is propertyNameString, and whose strict mode flag is
    strict.




An operative part for this question is step #5 above.



8.7.1 GetValue (V)



This describes how when the value being accessed is a property reference, it calls ToObject(base) to get the object version of any primitive.



9.9 ToObject



This describes how Boolean, Number and String primitives are converted to an object form with the [[PrimitiveValue]] internal property set accordingly.






As an interesting test, if the code was like this:



var x = null;
var a = x[0];


It would still not throw a SyntaxError at parse time as this is technically legal syntax, but it would throw a TypeError at runtime when you run the code because when the above Property Accessors logic is applied to the value of x, it will call CheckObjectCoercible(x) or call ToObject(x) which will both throw a TypeError if x is null or undefined.


[#38368] Tuesday, March 24, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
tayaw

Total Points: 749
Total Questions: 88
Total Answers: 86

Location: Djibouti
Member since Sun, Feb 27, 2022
2 Years ago
tayaw questions
;