Lorsque vous le faites 0[0], l'interpréteur JS transformera le premier 0en Numberobjet, puis essaiera d'accéder à la [0]propriété de cet objet qui est undefined.
Il n'y a pas d'erreur de syntaxe car la syntaxe d'accès aux propriétés 0[0]est autorisée par la grammaire du langage dans ce contexte. Cette structure (utilisant des termes dans la grammaire Javascript) est NumericLiteral[NumericLiteral].
La partie pertinente de la grammaire du langage de la section A.3 de la spécification ES5 ECMAScript est la suivante:
Literal ::
NullLiteral
BooleanLiteral
NumericLiteral
StringLiteral
RegularExpressionLiteral
PrimaryExpression :
this
Identifier
Literal
ArrayLiteral
ObjectLiteral
( Expression )
MemberExpression :
PrimaryExpression
FunctionExpression
MemberExpression [ Expression ]
MemberExpression . IdentifierName
new MemberExpression Arguments
Ainsi, on peut suivre la grammaire à travers cette progression:
MemberExpression [ Expression ]
PrimaryExpression [ Expression ]
Literal [ Expression ]
NumericLiteral [ Expression ]
Et, de même Expressionpeut aussi éventuellement l'être NumericLiteralaprès avoir suivi la grammaire, nous voyons que cela est autorisé:
NumericLiteral [ NumericLiteral ]
Ce qui signifie que 0[0]c'est une partie autorisée de la grammaire et donc pas de SyntaxError.
Ensuite, au moment de l'exécution, vous êtes autorisé à lire une propriété qui n'existe pas (elle sera simplement lue en tant que undefined) tant que la source que vous lisez est un objet ou a une conversion implicite en objet. Et, un littéral numérique a en effet une conversion implicite en un objet (un objet Number).
C'est l'une de ces fonctionnalités souvent inconnues de Javascript. Les types Number, Booleanet Stringen Javascript sont généralement stockées en interne comme primitives ( et non des objets à part entière). Il s'agit d'une représentation de stockage compacte et immuable (probablement réalisée de cette façon pour l'efficacité de la mise en œuvre). Mais, Javascript veut que vous puissiez traiter ces primitives comme des objets avec des propriétés et des méthodes. Ainsi, si vous essayez d'accéder à une propriété ou une méthode qui n'est pas directement prise en charge sur la primitive, Javascript contraindra temporairement la primitive dans un type d'objet approprié avec la valeur définie sur la valeur de la primitive.
Lorsque vous utilisez une syntaxe de type objet sur une primitive telle que 0[0], l'interpréteur le reconnaît comme un accès à une propriété sur une primitive. Sa réponse à cela est de prendre la première 0primitive numérique et de la forcer à devenir un Numberobjet à part entière sur lequel elle peut ensuite accéder à la [0]propriété. Dans ce cas spécifique, la [0]propriété d'un objet Number undefinedest la raison pour laquelle c'est la valeur que vous obtenez 0[0].
Voici un article sur l'auto-conversion d'une primitive en objet à des fins de gestion des propriétés:
La vie secrète des primitives Javascript
Voici les parties pertinentes de la spécification ECMAScript 5.1:
9.10 CheckObjectCoercible
Lance TypeError si la valeur est undefinedou null, sinon renvoie true.

11.2.1 Accesseurs de propriété
- Soit baseReference le résultat de l'évaluation de MemberExpression.
- Soit baseValue GetValue (baseReference).
- Soit propertyNameReference le résultat de l'évaluation d'Expression.
- Soit propertyNameValue GetValue (propertyNameReference).
- Appelez CheckObjectCoercible (baseValue).
- Soit propertyNameString ToString (propertyNameValue).
- Si la production syntaxique en cours d'évaluation est contenue dans du code en mode strict, laissez strict être vrai, sinon laissez strict être faux.
- Renvoie une valeur de type Reference dont la valeur de base est baseValue et dont le nom référencé est propertyNameString et dont l'indicateur de mode strict est strict.
Une partie opérationnelle de cette question est l'étape n ° 5 ci-dessus.
8.7.1 GetValue (V)
Cela décrit comment, lorsque la valeur en cours d'accès est une référence de propriété, elle appelle ToObject(base)pour obtenir la version objet de n'importe quelle primitive.
9.9 ToObject
Il décrit comment Boolean, Numberet Stringprimitives sont converties en une forme d'objet avec le [[PrimitiveValue]] de jeu de propriétés internes en conséquence.
Comme test intéressant, si le code était comme ça:
var x = null;
var a = x[0];
Cela ne lèverait toujours pas une SyntaxError au moment de l'analyse car il s'agit d'une syntaxe techniquement légale, mais cela lèverait une TypeError au moment de l'exécution lorsque vous exécutez le code car lorsque la logique des accesseurs de propriété ci-dessus est appliquée à la valeur de x, il appellera CheckObjectCoercible(x)ou appellera ToObject(x)qui lancera tous les deux une TypeError si xest nullou undefined.
true[0]ou""[0]